[XAPID-1002] add more tests
diff --git a/api.go b/api.go
index 55e5fcb..564dc8b 100644
--- a/api.go
+++ b/api.go
@@ -395,7 +395,7 @@
 	case http.StatusOK:
 		a.writePutRegisterResp(w, trackerResp)
 	default:
-		log.Infof("apiPutRegister code: %v Reason: %v", trackerResp.code, trackerResp.body)
+		log.Debugf("apiPutRegister code: %v Reason: %v", trackerResp.code, string(trackerResp.body))
 		a.writeError(w, trackerResp.code, API_ERR_FROM_TRACKER, string(trackerResp.body))
 	}
 
@@ -435,7 +435,7 @@
 	case http.StatusOK:
 		a.writeConfigStatusResp(w, trackerResp)
 	default:
-		log.Infof("apiPutConfigStatus code: %v Reason: %v", trackerResp.code, trackerResp.body)
+		log.Infof("apiPutConfigStatus code: %v Reason: %v", trackerResp.code, string(trackerResp.body))
 		a.writeError(w, trackerResp.code, API_ERR_FROM_TRACKER, string(trackerResp.body))
 	}
 }
@@ -583,6 +583,23 @@
 	ReportedTime  string              `json:"reportedTime"`
 }
 
+func (body *configStatusBody) validateBody() (bool, string) {
+	switch {
+	case !isValidUuid(body.ServiceId):
+		return false, "Bad/Missing gateway ServiceId"
+	case body.ReportedTime == "" || !isIso8601(body.ReportedTime):
+		return false, "Bad/Missing gateway reportedTime"
+	}
+
+	for _, s := range body.StatusDetails {
+		isValid, reason := s.validateBody()
+		if !isValid {
+			return false, reason
+		}
+	}
+	return true, ""
+}
+
 type statusDetailsJson struct {
 	Status          string `json:"status"`
 	ConfigurationId string `json:"configurationId"`
@@ -590,21 +607,12 @@
 	Message         string `json:"message"`
 }
 
-func (body *configStatusBody) validateBody() (bool, string) {
+func (s *statusDetailsJson) validateBody() (bool, string) {
 	switch {
-	case !isValidUuid(body.ServiceId):
-		return false, "Bad/Missing gateway ServiceId"
-	case body.ReportedTime == "":
-		return false, "Bad/Missing gateway reportedTime"
-	}
-
-	for _, s := range body.StatusDetails {
-		switch {
-		case s.Status == "":
-			return false, "Bad/Missing configuration Status"
-		case s.ConfigurationId == "":
-			return false, "Bad/Missing configuration ConfigurationId"
-		}
+	case s.Status == "":
+		return false, "Bad/Missing configuration Status"
+	case s.ConfigurationId == "":
+		return false, "Bad/Missing configuration ConfigurationId"
 	}
 	return true, ""
 }
diff --git a/api_test.go b/api_test.go
index 8178020..4cf93c0 100644
--- a/api_test.go
+++ b/api_test.go
@@ -25,8 +25,6 @@
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
 	mathrand "math/rand"
-	"os"
-	"reflect"
 	"strconv"
 	"strings"
 	"time"
@@ -394,6 +392,203 @@
 			})
 		})
 
+		Context("PUT /configurations/status", func() {
+			It("/configurations/status should validate request body", func() {
+				// setup test data
+				dummyClient.code = http.StatusOK
+				testData := [][]string{
+					{GenerateUUID(), time.Now().Format(iso8601)},
+					{GenerateUUID(), time.Now().Format(time.RFC3339)},
+					{GenerateUUID(), "invalid-time"},
+					{GenerateUUID(), time.Now().Format(time.RubyDate)},
+					{"invalid-uuid", time.Now().Format(iso8601)},
+					{"invalid-uuid", "invalid-time"},
+					{"", time.Now().Format(time.RFC3339)},
+					{GenerateUUID(), ""},
+				}
+
+				expectedCode := []int{
+					http.StatusOK,
+					http.StatusOK,
+					http.StatusBadRequest,
+					http.StatusBadRequest,
+					http.StatusBadRequest,
+					http.StatusBadRequest,
+					http.StatusBadRequest,
+					http.StatusBadRequest,
+				}
+
+				expectedBody := []string{
+					"",
+					"",
+					"reportedTime",
+					"reportedTime",
+					"ServiceId",
+					"ServiceId",
+					"ServiceId",
+					"reportedTime",
+				}
+
+				// setup http client
+				uri, err := url.Parse(apiTestUrl)
+				Expect(err).Should(Succeed())
+				for i, data := range testData {
+					uri.Path = testApiMan.configStatusEndpoint
+					log.Debug(uri.String())
+					configNum := mathrand.Intn(5)
+					statusDetails := make([]statusDetailsJson, 0)
+					expectedSlice := []string{}
+					for j := 0; j < configNum; j++ {
+						configStatus, expected := generateStatusDetails(0)
+						statusDetails = append(statusDetails, *configStatus)
+						expectedSlice = append(expectedSlice, expected)
+					}
+
+					expectedSlice = append(expectedSlice, data...)
+
+					if expectedCode[i] == http.StatusOK {
+						expectedBody[i] = strings.Join(expectedSlice, " ")
+					}
+
+					reqBody, err := json.Marshal(configStatusBody{
+						ServiceId:     data[0],
+						ReportedTime:  data[1],
+						StatusDetails: statusDetails,
+					})
+					Expect(err).Should(Succeed())
+					req, err := http.NewRequest("PUT", uri.String(), bytes.NewReader(reqBody))
+					Expect(err).Should(Succeed())
+					// http put
+					res, err := testClient.Do(req)
+					Expect(err).Should(Succeed())
+					// parse response
+					defer res.Body.Close()
+					Expect(res.StatusCode).Should(Equal(expectedCode[i]))
+					body, err := ioutil.ReadAll(res.Body)
+					Expect(err).Should(Succeed())
+					Expect(strings.Contains(strings.ToLower(string(body)), strings.ToLower(expectedBody[i]))).To(BeTrue())
+				}
+			})
+
+			It("/configurations/status should validate status detail", func() {
+				// setup test data
+				dummyClient.code = http.StatusOK
+				testData := [][]string{
+					{GenerateUUID(), time.Now().Format(iso8601)},
+					{GenerateUUID(), time.Now().Format(iso8601)},
+				}
+
+				expectedCode := []int{
+					http.StatusBadRequest,
+					http.StatusBadRequest,
+				}
+
+				expectedBody := []string{
+					"Status",
+					"ConfigurationId",
+				}
+
+				// setup http client
+				uri, err := url.Parse(apiTestUrl)
+				Expect(err).Should(Succeed())
+				for i, data := range testData {
+					uri.Path = testApiMan.configStatusEndpoint
+					log.Debug(uri.String())
+					configNum := mathrand.Intn(5) + 1
+					statusDetails := make([]statusDetailsJson, 0)
+					expectedSlice := []string{}
+					for j := 0; j < configNum; j++ {
+						configStatus, expected := generateStatusDetails(i + 1)
+						statusDetails = append(statusDetails, *configStatus)
+						expectedSlice = append(expectedSlice, expected)
+					}
+
+					expectedSlice = append(expectedSlice, data...)
+
+					reqBody, err := json.Marshal(configStatusBody{
+						ServiceId:     data[0],
+						ReportedTime:  data[1],
+						StatusDetails: statusDetails,
+					})
+					Expect(err).Should(Succeed())
+					req, err := http.NewRequest("PUT", uri.String(), bytes.NewReader(reqBody))
+					Expect(err).Should(Succeed())
+					// http put
+					res, err := testClient.Do(req)
+					Expect(err).Should(Succeed())
+					// parse response
+					defer res.Body.Close()
+					Expect(res.StatusCode).Should(Equal(expectedCode[i]))
+					body, err := ioutil.ReadAll(res.Body)
+					Expect(err).Should(Succeed())
+					Expect(strings.Contains(strings.ToLower(string(body)), strings.ToLower(expectedBody[i]))).To(BeTrue())
+				}
+			})
+
+			It("/configurations/status should populate errors from tracker", func() {
+				// setup test data
+				testData := [][]string{
+					{GenerateUUID(), time.Now().Format(iso8601)},
+					{GenerateUUID(), time.Now().Format(iso8601)},
+					{GenerateUUID(), time.Now().Format(iso8601)},
+				}
+
+				expectedCode := []int{
+					http.StatusBadRequest,
+					http.StatusInternalServerError,
+					http.StatusBadGateway,
+				}
+
+				expectedBody := []string{
+					"",
+					"",
+					"",
+				}
+
+				// setup http client
+				uri, err := url.Parse(apiTestUrl)
+				Expect(err).Should(Succeed())
+				for i, data := range testData {
+					uri.Path = testApiMan.configStatusEndpoint
+					log.Debug(uri.String())
+					configNum := mathrand.Intn(5)
+					statusDetails := make([]statusDetailsJson, 0)
+					expectedSlice := []string{}
+					for j := 0; j < configNum; j++ {
+						configStatus, expected := generateStatusDetails(0)
+						statusDetails = append(statusDetails, *configStatus)
+						expectedSlice = append(expectedSlice, expected)
+					}
+
+					expectedSlice = append(expectedSlice, data...)
+
+					if expectedCode[i] == http.StatusOK {
+						expectedBody[i] = strings.Join(expectedSlice, " ")
+					}
+
+					reqBody, err := json.Marshal(configStatusBody{
+						ServiceId:     data[0],
+						ReportedTime:  data[1],
+						StatusDetails: statusDetails,
+					})
+					Expect(err).Should(Succeed())
+					req, err := http.NewRequest("PUT", uri.String(), bytes.NewReader(reqBody))
+					Expect(err).Should(Succeed())
+
+					dummyClient.code = expectedCode[i]
+					// http put
+					res, err := testClient.Do(req)
+					Expect(err).Should(Succeed())
+					// parse response
+					defer res.Body.Close()
+					Expect(res.StatusCode).Should(Equal(expectedCode[i]))
+					body, err := ioutil.ReadAll(res.Body)
+					Expect(err).Should(Succeed())
+					Expect(strings.Contains(strings.ToLower(string(body)), strings.ToLower(expectedBody[i]))).To(BeTrue())
+				}
+			})
+		})
+
 		Context("PUT /register/{uuid}", func() {
 			It("/register should validate request", func() {
 				// setup test data
@@ -483,6 +678,57 @@
 					Expect(strings.Contains(strings.ToLower(string(body)), strings.ToLower(expectedBody[i]))).To(BeTrue())
 				}
 			})
+
+			It("/register should populate errors from tracker", func() {
+				// setup test data
+				testData := [][]string{
+					{GenerateUUID(), "pod", "podType", time.Now().Format(iso8601), "name", "type"},
+					{GenerateUUID(), "pod", "podType", time.Now().Format(iso8601), "name", "type"},
+					{GenerateUUID(), "pod", "podType", time.Now().Format(iso8601), "name", "type"},
+				}
+
+				expectedCode := []int{
+					http.StatusBadRequest,
+					http.StatusInternalServerError,
+					http.StatusBadGateway,
+				}
+
+				expectedBody := []string{
+					strings.Join(testData[0], " "),
+					strings.Join(testData[1], " "),
+					strings.Join(testData[2], " "),
+				}
+
+				// setup http client
+				uri, err := url.Parse(apiTestUrl)
+				Expect(err).Should(Succeed())
+				for i, data := range testData {
+					dummyClient.code = expectedCode[i]
+					uuid := data[0]
+					uri.Path = strings.Replace(testApiMan.registerEndpoint, "{uuid}", uuid, 1)
+					reqBody, err := json.Marshal(registerBody{
+						Uuid:         data[0],
+						Pod:          data[1],
+						PodType:      data[2],
+						ReportedTime: data[3],
+						Name:         data[4],
+						Type:         data[5],
+					})
+					Expect(err).Should(Succeed())
+					log.Debug(uri.String())
+					req, err := http.NewRequest("PUT", uri.String(), bytes.NewReader(reqBody))
+					Expect(err).Should(Succeed())
+					// http put
+					res, err := testClient.Do(req)
+					Expect(err).Should(Succeed())
+					// parse response
+					defer res.Body.Close()
+					Expect(res.StatusCode).Should(Equal(expectedCode[i]))
+					body, err := ioutil.ReadAll(res.Body)
+					Expect(err).Should(Succeed())
+					Expect(strings.Contains(strings.ToLower(string(body)), strings.ToLower(expectedBody[i]))).To(BeTrue())
+				}
+			})
 		})
 	})
 
@@ -544,48 +790,6 @@
 	return detail
 }
 
-type dummyDbManager struct {
-	unreadyBlobIds   []string
-	readyDeployments []DataDeployment
-	localFSLocation  string
-	fileResponse     chan string
-	version          string
-}
-
-func (d *dummyDbManager) setDbVersion(version string) {
-	d.version = version
-}
-
-func (d *dummyDbManager) initDb() error {
-	return nil
-}
-
-func (d *dummyDbManager) getUnreadyBlobs() ([]string, error) {
-	return d.unreadyBlobIds, nil
-}
-
-func (d *dummyDbManager) getReadyDeployments() ([]DataDeployment, error) {
-	return d.readyDeployments, nil
-}
-
-func (d *dummyDbManager) updateLocalFsLocation(blobId, localFsLocation string) error {
-	file, err := os.Open(localFsLocation)
-	if err != nil {
-		return err
-	}
-	buff := make([]byte, 36)
-	_, err = file.Read(buff)
-	if err != nil {
-		return err
-	}
-	d.fileResponse <- string(buff)
-	return nil
-}
-
-func (d *dummyDbManager) getLocalFSLocation(string) (string, error) {
-	return d.localFSLocation, nil
-}
-
 func GenerateUUID() string {
 
 	buff := make([]byte, 16)
@@ -599,43 +803,37 @@
 	return fmt.Sprintf("%x-%x-%x-%x-%x", buff[0:4], buff[4:6], buff[6:8], buff[8:10], buff[10:])
 }
 
-type dummyTrackerClient struct {
-	code int
-	args []string
-}
-
-func (d *dummyTrackerClient) putConfigStatus(reqBody *configStatusBody) *trackerResponse {
-
-	return &trackerResponse{
-		code:        d.code,
-		contentType: "application/octet-stream",
-		body:        []byte(concatenateFields(reqBody)),
+func generateStatusDetails(flag int) (*statusDetailsJson, string) {
+	log.Warnf("flag: %v", flag)
+	id := GenerateUUID()
+	var ret *statusDetailsJson
+	var expected string
+	switch flag {
+	case 1: // invalid Status
+		ret = &statusDetailsJson{
+			Status:          "",
+			ConfigurationId: id,
+			ErrorCode:       "errorcode" + id,
+			Message:         "message" + id,
+		}
+		expected = "Status"
+	case 2: // invalid ConfigurationId
+		ret = &statusDetailsJson{
+			Status:          "status" + id,
+			ConfigurationId: "",
+			ErrorCode:       "errorcode" + id,
+			Message:         "message" + id,
+		}
+		expected = "ConfigurationId"
+	default:
+		ret = &statusDetailsJson{
+			Status:          "status" + id,
+			ConfigurationId: id,
+			ErrorCode:       "errorcode" + id,
+			Message:         "message" + id,
+		}
+		expected = strings.Join([]string{ret.Status, ret.ConfigurationId, ret.ErrorCode, ret.Message}, " ")
 	}
-}
 
-func (d *dummyTrackerClient) putRegister(uuid string, reqBody *registerBody) *trackerResponse {
-
-	return &trackerResponse{
-		code:        d.code,
-		contentType: "application/octet-stream",
-		body:        []byte(concatenateFields(reqBody)),
-	}
-}
-
-func (d *dummyTrackerClient) putHeartbeat(uuid, reported string) *trackerResponse {
-	return &trackerResponse{
-		code:        d.code,
-		contentType: "application/octet-stream",
-		body:        []byte(uuid + " " + reported),
-	}
-}
-
-func concatenateFields(s interface{}) string {
-	v := reflect.ValueOf(s).Elem()
-	fields := []string{}
-	for i := 0; i < v.NumField(); i++ {
-		fields = append(fields, v.Field(i).String())
-	}
-	log.Warn(strings.Join(fields, " "))
-	return strings.Join(fields, " ")
+	return ret, expected
 }
diff --git a/bundle_test.go b/bundle_test.go
index 7946f96..649e251 100644
--- a/bundle_test.go
+++ b/bundle_test.go
@@ -15,15 +15,8 @@
 package apiGatewayConfDeploy
 
 import (
-	"net/http"
-
-	"bytes"
-	"encoding/json"
-	"github.com/gorilla/mux"
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
-	"io"
-	"strings"
 	"sync/atomic"
 	"time"
 )
@@ -136,71 +129,3 @@
 		Expect(req.markFailedAt.IsZero()).Should(BeTrue())
 	}, 4)
 })
-
-type dummyApiManager struct {
-	initCalled bool
-}
-
-func (a *dummyApiManager) InitAPI() {
-	a.initCalled = true
-}
-
-type dummyBlobServer struct {
-	serverEndpoint string
-	signedEndpoint string
-	signedTimeout  *int32
-	blobTimeout    *int32
-	resetTimeout   bool
-}
-
-func (b *dummyBlobServer) start() {
-	services.API().HandleFunc(b.serverEndpoint, b.returnSigned).Methods("GET")
-	services.API().HandleFunc(b.signedEndpoint, b.returnBlob).Methods("GET")
-}
-
-// send a dummy uri as response
-func (b *dummyBlobServer) returnSigned(w http.ResponseWriter, r *http.Request) {
-	defer GinkgoRecover()
-	if atomic.LoadInt32(b.signedTimeout) == int32(1) {
-		if b.resetTimeout {
-			atomic.StoreInt32(b.signedTimeout, 0)
-		}
-		time.Sleep(time.Second)
-	}
-	vars := mux.Vars(r)
-	blobId := vars["blobId"]
-
-	uriString := strings.Replace(bundleTestUrl+b.signedEndpoint, "{blobId}", blobId, 1)
-	log.Debug("dummyBlobServer returnSigned: " + uriString)
-
-	res := blobServerResponse{
-		Id:                       blobId,
-		Kind:                     "Blob",
-		Self:                     r.RequestURI,
-		SignedUrl:                uriString,
-		SignedUrlExpiryTimestamp: time.Now().Add(3 * time.Hour).Format(time.RFC3339),
-	}
-
-	resBytes, err := json.Marshal(res)
-	Expect(err).Should(Succeed())
-	_, err = io.Copy(w, bytes.NewReader(resBytes))
-	Expect(err).Should(Succeed())
-	w.Header().Set("Content-Type", headerSteam)
-}
-
-// send blobId back as response
-func (b *dummyBlobServer) returnBlob(w http.ResponseWriter, r *http.Request) {
-	defer GinkgoRecover()
-	if atomic.LoadInt32(b.blobTimeout) == int32(1) {
-		if b.resetTimeout {
-			atomic.StoreInt32(b.blobTimeout, 0)
-		}
-		time.Sleep(time.Second)
-	}
-	vars := mux.Vars(r)
-	blobId := vars["blobId"]
-	log.Debug("dummyBlobServer returnBlob id=" + blobId)
-	_, err := io.Copy(w, bytes.NewReader([]byte(blobId)))
-	Expect(err).Should(Succeed())
-	w.Header().Set("Content-Type", headerSteam)
-}
diff --git a/listener_test.go b/listener_test.go
index 7549efb..41ad076 100644
--- a/listener_test.go
+++ b/listener_test.go
@@ -277,45 +277,6 @@
 	})
 })
 
-type dummyBundleManager struct {
-	requestChan chan *DownloadRequest
-	depChan     chan *DataDeployment
-	delChan     chan *DataDeployment
-	delBlobChan chan string
-}
-
-func (bm *dummyBundleManager) initializeBundleDownloading() {
-
-}
-
-func (bm *dummyBundleManager) queueDownloadRequest(dep *DataDeployment) {
-	bm.depChan <- dep
-}
-
-func (bm *dummyBundleManager) enqueueRequest(req *DownloadRequest) {
-	bm.requestChan <- req
-}
-
-func (bm *dummyBundleManager) makeDownloadRequest(blobId string) *DownloadRequest {
-	return &DownloadRequest{
-		blobId: blobId,
-	}
-}
-
-func (bm *dummyBundleManager) deleteBundlesFromDeployments(deployments []DataDeployment) {
-	for i := range deployments {
-		bm.delChan <- &deployments[i]
-	}
-}
-
-func (bm *dummyBundleManager) deleteBundleById(blobId string) {
-	bm.delBlobChan <- blobId
-}
-
-func (bm *dummyBundleManager) Close() {
-
-}
-
 func rowFromDeployment(dep *DataDeployment) common.Row {
 	row := common.Row{}
 	row["id"] = &common.ColumnVal{Value: dep.ID}
diff --git a/test_mocks_test.go b/test_mocks_test.go
new file mode 100644
index 0000000..7f0d4cd
--- /dev/null
+++ b/test_mocks_test.go
@@ -0,0 +1,228 @@
+// Copyright 2017 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package apiGatewayConfDeploy
+
+import (
+	"bytes"
+	"encoding/json"
+	"github.com/gorilla/mux"
+	. "github.com/onsi/ginkgo"
+	. "github.com/onsi/gomega"
+	"io"
+	"net/http"
+	"os"
+	"reflect"
+	"strings"
+	"sync/atomic"
+	"time"
+)
+
+type dummyTrackerClient struct {
+	code int
+	args []string
+}
+
+func (d *dummyTrackerClient) putConfigStatus(reqBody *configStatusBody) *trackerResponse {
+
+	return &trackerResponse{
+		code:        d.code,
+		contentType: "application/octet-stream",
+		body:        []byte(concatenateFields(reqBody)),
+	}
+}
+
+func (d *dummyTrackerClient) putRegister(uuid string, reqBody *registerBody) *trackerResponse {
+
+	return &trackerResponse{
+		code:        d.code,
+		contentType: "application/octet-stream",
+		body:        []byte(concatenateFields(reqBody)),
+	}
+}
+
+func (d *dummyTrackerClient) putHeartbeat(uuid, reported string) *trackerResponse {
+	return &trackerResponse{
+		code:        d.code,
+		contentType: "application/octet-stream",
+		body:        []byte(uuid + " " + reported),
+	}
+}
+func concatenateFields(s interface{}) string {
+	v := reflect.ValueOf(s).Elem()
+	return recursiveSerialize(v)
+}
+
+func recursiveSerialize(v reflect.Value) string {
+	fields := []string{}
+	for i := 0; i < v.NumField(); i++ {
+		field := v.Field(i)
+		if field.Type().Kind() == reflect.Slice {
+			for j := 0; j < field.Len(); j++ {
+				fields = append(fields, recursiveSerialize(field.Index(j)))
+			}
+		} else {
+			fields = append(fields, field.String())
+		}
+	}
+	return strings.Join(fields, " ")
+}
+
+type dummyDbManager struct {
+	unreadyBlobIds   []string
+	readyDeployments []DataDeployment
+	localFSLocation  string
+	fileResponse     chan string
+	version          string
+}
+
+func (d *dummyDbManager) setDbVersion(version string) {
+	d.version = version
+}
+
+func (d *dummyDbManager) initDb() error {
+	return nil
+}
+
+func (d *dummyDbManager) getUnreadyBlobs() ([]string, error) {
+	return d.unreadyBlobIds, nil
+}
+
+func (d *dummyDbManager) getReadyDeployments() ([]DataDeployment, error) {
+	return d.readyDeployments, nil
+}
+
+func (d *dummyDbManager) updateLocalFsLocation(blobId, localFsLocation string) error {
+	file, err := os.Open(localFsLocation)
+	if err != nil {
+		return err
+	}
+	buff := make([]byte, 36)
+	_, err = file.Read(buff)
+	if err != nil {
+		return err
+	}
+	d.fileResponse <- string(buff)
+	return nil
+}
+
+func (d *dummyDbManager) getLocalFSLocation(string) (string, error) {
+	return d.localFSLocation, nil
+}
+
+type dummyBundleManager struct {
+	requestChan chan *DownloadRequest
+	depChan     chan *DataDeployment
+	delChan     chan *DataDeployment
+	delBlobChan chan string
+}
+
+func (bm *dummyBundleManager) initializeBundleDownloading() {
+
+}
+
+func (bm *dummyBundleManager) queueDownloadRequest(dep *DataDeployment) {
+	bm.depChan <- dep
+}
+
+func (bm *dummyBundleManager) enqueueRequest(req *DownloadRequest) {
+	bm.requestChan <- req
+}
+
+func (bm *dummyBundleManager) makeDownloadRequest(blobId string) *DownloadRequest {
+	return &DownloadRequest{
+		blobId: blobId,
+	}
+}
+
+func (bm *dummyBundleManager) deleteBundlesFromDeployments(deployments []DataDeployment) {
+	for i := range deployments {
+		bm.delChan <- &deployments[i]
+	}
+}
+
+func (bm *dummyBundleManager) deleteBundleById(blobId string) {
+	bm.delBlobChan <- blobId
+}
+
+func (bm *dummyBundleManager) Close() {
+
+}
+
+type dummyApiManager struct {
+	initCalled bool
+}
+
+func (a *dummyApiManager) InitAPI() {
+	a.initCalled = true
+}
+
+type dummyBlobServer struct {
+	serverEndpoint string
+	signedEndpoint string
+	signedTimeout  *int32
+	blobTimeout    *int32
+	resetTimeout   bool
+}
+
+func (b *dummyBlobServer) start() {
+	services.API().HandleFunc(b.serverEndpoint, b.returnSigned).Methods("GET")
+	services.API().HandleFunc(b.signedEndpoint, b.returnBlob).Methods("GET")
+}
+
+// send a dummy uri as response
+func (b *dummyBlobServer) returnSigned(w http.ResponseWriter, r *http.Request) {
+	defer GinkgoRecover()
+	if atomic.LoadInt32(b.signedTimeout) == int32(1) {
+		if b.resetTimeout {
+			atomic.StoreInt32(b.signedTimeout, 0)
+		}
+		time.Sleep(time.Second)
+	}
+	vars := mux.Vars(r)
+	blobId := vars["blobId"]
+
+	uriString := strings.Replace(bundleTestUrl+b.signedEndpoint, "{blobId}", blobId, 1)
+	log.Debug("dummyBlobServer returnSigned: " + uriString)
+
+	res := blobServerResponse{
+		Id:                       blobId,
+		Kind:                     "Blob",
+		Self:                     r.RequestURI,
+		SignedUrl:                uriString,
+		SignedUrlExpiryTimestamp: time.Now().Add(3 * time.Hour).Format(time.RFC3339),
+	}
+
+	resBytes, err := json.Marshal(res)
+	Expect(err).Should(Succeed())
+	_, err = io.Copy(w, bytes.NewReader(resBytes))
+	Expect(err).Should(Succeed())
+	w.Header().Set("Content-Type", headerSteam)
+}
+
+// send blobId back as response
+func (b *dummyBlobServer) returnBlob(w http.ResponseWriter, r *http.Request) {
+	defer GinkgoRecover()
+	if atomic.LoadInt32(b.blobTimeout) == int32(1) {
+		if b.resetTimeout {
+			atomic.StoreInt32(b.blobTimeout, 0)
+		}
+		time.Sleep(time.Second)
+	}
+	vars := mux.Vars(r)
+	blobId := vars["blobId"]
+	log.Debug("dummyBlobServer returnBlob id=" + blobId)
+	_, err := io.Copy(w, bytes.NewReader([]byte(blobId)))
+	Expect(err).Should(Succeed())
+	w.Header().Set("Content-Type", headerSteam)
+}