diff --git a/pkg/client/install.go b/pkg/client/install.go
index 59e53c367d176b56d01c4949628188877ae967d5..8a582f2d1619e11df2b8628e9615ac475e37b91c 100644
--- a/pkg/client/install.go
+++ b/pkg/client/install.go
@@ -43,7 +43,7 @@ func (i *Installer) Install() error {
 		return err
 	}
 
-	return kube.Create("helm", &b, nil)
+	return kube.New(nil).Create("helm", &b)
 }
 
 // InstallYAML is the installation YAML for DM.
diff --git a/pkg/kube/client.go b/pkg/kube/client.go
index 7f6acf02977f102d50828b20c58db71ee98af7ea..0fa72473dede1462b5ff6a8ed2cbfbb7883bbb47 100644
--- a/pkg/kube/client.go
+++ b/pkg/kube/client.go
@@ -9,7 +9,17 @@ import (
 	"k8s.io/kubernetes/pkg/kubectl/resource"
 )
 
-const includeThirdPartyAPIs = false
+// Client represents a client capable of communicating with the Kubernetes API.
+type Client struct {
+	config clientcmd.ClientConfig
+}
+
+// New create a new Client
+func New(config clientcmd.ClientConfig) *Client {
+	return &Client{
+		config: config,
+	}
+}
 
 // ResourceActorFunc performs an action on a signle resource.
 type ResourceActorFunc func(*resource.Info) error
@@ -17,12 +27,13 @@ type ResourceActorFunc func(*resource.Info) error
 // Create creates kubernetes resources from an io.reader
 //
 // Namespace will set the namespace
-// Config allows for overiding values from kubectl
-func Create(namespace string, reader io.Reader, config clientcmd.ClientConfig) error {
-	f := cmdutil.NewFactory(config)
+func (c *Client) Create(namespace string, reader io.Reader) error {
+	f := cmdutil.NewFactory(c.config)
 	return perform(f, namespace, reader, createResource)
 }
 
+const includeThirdPartyAPIs = false
+
 func perform(f *cmdutil.Factory, namespace string, reader io.Reader, fn ResourceActorFunc) error {
 	r := f.NewBuilder(includeThirdPartyAPIs).
 		ContinueOnError().
diff --git a/pkg/kube/client_test.go b/pkg/kube/client_test.go
index daeb3dee4ed4c6d0b47eafddfcd8c801899b2485..a13d4c1ab1a3904cfd5300c9f588918237a21c7f 100644
--- a/pkg/kube/client_test.go
+++ b/pkg/kube/client_test.go
@@ -1,7 +1,8 @@
 package kube
 
 import (
-	"os"
+	"io"
+	"strings"
 	"testing"
 
 	"k8s.io/kubernetes/pkg/api/meta"
@@ -11,34 +12,179 @@ import (
 )
 
 func TestPerform(t *testing.T) {
-	input, err := os.Open("./testdata/guestbook-all-in-one.yaml")
-	if err != nil {
-		t.Fatal(err)
+	tests := []struct {
+		name       string
+		namespace  string
+		reader     io.Reader
+		count      int
+		err        bool
+		errMessage string
+	}{
+		{
+			name:      "Valid input",
+			namespace: "test",
+			reader:    strings.NewReader(guestbookManifest),
+			count:     6,
+		}, {
+			name:       "Empty manifests",
+			namespace:  "test",
+			reader:     strings.NewReader(""),
+			err:        true,
+			errMessage: "no objects passed to create",
+		},
 	}
-	defer input.Close()
 
-	results := []*resource.Info{}
+	for _, tt := range tests {
+		results := []*resource.Info{}
 
-	fn := func(info *resource.Info) error {
-		results = append(results, info)
+		fn := func(info *resource.Info) error {
+			results = append(results, info)
 
-		if info.Namespace != "test" {
-			t.Errorf("expected namespace to be 'test', got %s", info.Namespace)
+			if info.Namespace != tt.namespace {
+				t.Errorf("%q. expected namespace to be '%s', got %s", tt.name, tt.namespace, info.Namespace)
+			}
+			return nil
 		}
 
-		return nil
-	}
-
-	f := cmdutil.NewFactory(nil)
-	f.ClientForMapping = func(mapping *meta.RESTMapping) (resource.RESTClient, error) {
-		return &fake.RESTClient{}, nil
-	}
+		f := cmdutil.NewFactory(nil)
+		f.ClientForMapping = func(mapping *meta.RESTMapping) (resource.RESTClient, error) {
+			return &fake.RESTClient{}, nil
+		}
 
-	if err := perform(f, "test", input, fn); err != nil {
-		t.Fatalf("Unexpected error: %s", err)
-	}
+		err := perform(f, tt.namespace, tt.reader, fn)
+		if (err != nil) != tt.err {
+			t.Errorf("%q. expected error: %v, got %v", tt.name, tt.err, err)
+		}
+		if err != nil && err.Error() != tt.errMessage {
+			t.Errorf("%q. expected error message: %v, got %v", tt.name, tt.errMessage, err)
+		}
 
-	if len(results) != 6 {
-		t.Errorf("expected 6 result objects, got %d", len(results))
+		if len(results) != tt.count {
+			t.Errorf("%q. expected %d result objects, got %d", tt.name, tt.count, len(results))
+		}
 	}
 }
+
+const guestbookManifest = `
+apiVersion: v1
+kind: Service
+metadata:
+  name: redis-master
+  labels:
+    app: redis
+    tier: backend
+    role: master
+spec:
+  ports:
+  - port: 6379
+    targetPort: 6379
+  selector:
+    app: redis
+    tier: backend
+    role: master
+---
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+  name: redis-master
+spec:
+  replicas: 1
+  template:
+    metadata:
+      labels:
+        app: redis
+        role: master
+        tier: backend
+    spec:
+      containers:
+      - name: master
+        image: gcr.io/google_containers/redis:e2e  # or just image: redis
+        resources:
+          requests:
+            cpu: 100m
+            memory: 100Mi
+        ports:
+        - containerPort: 6379
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: redis-slave
+  labels:
+    app: redis
+    tier: backend
+    role: slave
+spec:
+  ports:
+    # the port that this service should serve on
+  - port: 6379
+  selector:
+    app: redis
+    tier: backend
+    role: slave
+---
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+  name: redis-slave
+spec:
+  replicas: 2
+  template:
+    metadata:
+      labels:
+        app: redis
+        role: slave
+        tier: backend
+    spec:
+      containers:
+      - name: slave
+        image: gcr.io/google_samples/gb-redisslave:v1
+        resources:
+          requests:
+            cpu: 100m
+            memory: 100Mi
+        env:
+        - name: GET_HOSTS_FROM
+          value: dns
+        ports:
+        - containerPort: 6379
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: frontend
+  labels:
+    app: guestbook
+    tier: frontend
+spec:
+  ports:
+  - port: 80
+  selector:
+    app: guestbook
+    tier: frontend
+---
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+  name: frontend
+spec:
+  replicas: 3
+  template:
+    metadata:
+      labels:
+        app: guestbook
+        tier: frontend
+    spec:
+      containers:
+      - name: php-redis
+        image: gcr.io/google-samples/gb-frontend:v4
+        resources:
+          requests:
+            cpu: 100m
+            memory: 100Mi
+        env:
+        - name: GET_HOSTS_FROM
+          value: dns
+        ports:
+        - containerPort: 80
+`
diff --git a/pkg/kube/testdata/guestbook-all-in-one.yaml b/pkg/kube/testdata/guestbook-all-in-one.yaml
deleted file mode 100644
index c6675e0eb673a954d791d0684fdcf09a89bc435b..0000000000000000000000000000000000000000
--- a/pkg/kube/testdata/guestbook-all-in-one.yaml
+++ /dev/null
@@ -1,179 +0,0 @@
-apiVersion: v1
-kind: Service
-metadata:
-  name: redis-master
-  labels:
-    app: redis
-    tier: backend
-    role: master
-spec:
-  ports:
-    # the port that this service should serve on
-  - port: 6379
-    targetPort: 6379
-  selector:
-    app: redis
-    tier: backend
-    role: master
----
-apiVersion: extensions/v1beta1
-kind: Deployment
-metadata:
-  name: redis-master
-  # these labels can be applied automatically
-  # from the labels in the pod template if not set
-  # labels:
-  #   app: redis
-  #   role: master
-  #   tier: backend
-spec:
-  # this replicas value is default
-  # modify it according to your case
-  replicas: 1
-  # selector can be applied automatically
-  # from the labels in the pod template if not set
-  # selector:
-  #   matchLabels:
-  #     app: guestbook
-  #     role: master
-  #     tier: backend
-  template:
-    metadata:
-      labels:
-        app: redis
-        role: master
-        tier: backend
-    spec:
-      containers:
-      - name: master
-        image: gcr.io/google_containers/redis:e2e  # or just image: redis
-        resources:
-          requests:
-            cpu: 100m
-            memory: 100Mi
-        ports:
-        - containerPort: 6379
----
-apiVersion: v1
-kind: Service
-metadata:
-  name: redis-slave
-  labels:
-    app: redis
-    tier: backend
-    role: slave
-spec:
-  ports:
-    # the port that this service should serve on
-  - port: 6379
-  selector:
-    app: redis
-    tier: backend
-    role: slave
----
-apiVersion: extensions/v1beta1
-kind: Deployment
-metadata:
-  name: redis-slave
-  # these labels can be applied automatically
-  # from the labels in the pod template if not set
-  # labels:
-  #   app: redis
-  #   role: slave
-  #   tier: backend
-spec:
-  # this replicas value is default
-  # modify it according to your case
-  replicas: 2
-  # selector can be applied automatically
-  # from the labels in the pod template if not set
-  # selector:
-  #   matchLabels:
-  #     app: guestbook
-  #     role: slave
-  #     tier: backend
-  template:
-    metadata:
-      labels:
-        app: redis
-        role: slave
-        tier: backend
-    spec:
-      containers:
-      - name: slave
-        image: gcr.io/google_samples/gb-redisslave:v1
-        resources:
-          requests:
-            cpu: 100m
-            memory: 100Mi
-        env:
-        - name: GET_HOSTS_FROM
-          value: dns
-          # If your cluster config does not include a dns service, then to
-          # instead access an environment variable to find the master
-          # service's host, comment out the 'value: dns' line above, and
-          # uncomment the line below.
-          # value: env
-        ports:
-        - containerPort: 6379
----
-apiVersion: v1
-kind: Service
-metadata:
-  name: frontend
-  labels:
-    app: guestbook
-    tier: frontend
-spec:
-  # if your cluster supports it, uncomment the following to automatically create
-  # an external load-balanced IP for the frontend service.
-  # type: LoadBalancer
-  ports:
-    # the port that this service should serve on
-  - port: 80
-  selector:
-    app: guestbook
-    tier: frontend
----
-apiVersion: extensions/v1beta1
-kind: Deployment
-metadata:
-  name: frontend
-  # these labels can be applied automatically
-  # from the labels in the pod template if not set
-  # labels:
-  #   app: guestbook
-  #   tier: frontend
-spec:
-  # this replicas value is default
-  # modify it according to your case
-  replicas: 3
-  # selector can be applied automatically
-  # from the labels in the pod template if not set
-  # selector:
-  #   matchLabels:
-  #     app: guestbook
-  #     tier: frontend
-  template:
-    metadata:
-      labels:
-        app: guestbook
-        tier: frontend
-    spec:
-      containers:
-      - name: php-redis
-        image: gcr.io/google-samples/gb-frontend:v4
-        resources:
-          requests:
-            cpu: 100m
-            memory: 100Mi
-        env:
-        - name: GET_HOSTS_FROM
-          value: dns
-          # If your cluster config does not include a dns service, then to
-          # instead access environment variables to find service host
-          # info, comment out the 'value: dns' line above, and uncomment the
-          # line below.
-          # value: env
-        ports:
-        - containerPort: 80