diff --git a/pkg/cluster/initinfra/infra_test.go b/pkg/cluster/initinfra/infra_test.go
index 2d89813bd..73e889da0 100644
--- a/pkg/cluster/initinfra/infra_test.go
+++ b/pkg/cluster/initinfra/infra_test.go
@@ -60,9 +60,6 @@ func TestDeploy(t *testing.T) {
 	infra.FileSystem = document.NewDocumentFs()
 
 	kctl := kubectl.NewKubectl(tf)
-	tc := fake.Client{
-		MockKubectl: func() kubectl.Interface { return kctl },
-	}
 
 	tests := []struct {
 		theInfra      *initinfra.Infra
@@ -71,24 +68,22 @@ func TestDeploy(t *testing.T) {
 		expectedError error
 	}{
 		{
-			client: fake.Client{
-				MockKubectl: func() kubectl.Interface {
-					return kubectl.NewKubectl(k8sutils.
-						NewMockKubectlFactory().
-						WithDynamicClientByError(nil, DynamicClientError))
-				},
-			},
+
+			client: fake.NewClient(fake.WithKubectl(
+				kubectl.NewKubectl(k8sutils.
+					NewMockKubectlFactory().
+					WithDynamicClientByError(nil, DynamicClientError)))),
 			expectedError: DynamicClientError,
 		},
 		{
 			expectedError: nil,
 			prune:         false,
-			client:        tc,
+			client:        fake.NewClient(fake.WithKubectl(kctl)),
 		},
 		{
 			expectedError: nil,
 			prune:         true,
-			client:        tc,
+			client:        fake.NewClient(fake.WithKubectl(kctl)),
 		},
 	}
 
diff --git a/pkg/cluster/status_test.go b/pkg/cluster/status_test.go
index 83b8d4181..07bb4e65d 100644
--- a/pkg/cluster/status_test.go
+++ b/pkg/cluster/status_test.go
@@ -22,9 +22,6 @@ import (
 	"github.com/stretchr/testify/require"
 
 	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
-	"k8s.io/apimachinery/pkg/runtime"
-	"k8s.io/client-go/dynamic"
-	dynamicFake "k8s.io/client-go/dynamic/fake"
 
 	"opendev.org/airship/airshipctl/pkg/cluster"
 	"opendev.org/airship/airshipctl/pkg/document"
@@ -107,7 +104,7 @@ func TestGetStatusForResource(t *testing.T) {
 	tests := []struct {
 		name           string
 		selector       document.Selector
-		testClient     fake.Client
+		testClient     *fake.Client
 		expectedStatus cluster.Status
 		err            error
 	}{
@@ -116,7 +113,9 @@ func TestGetStatusForResource(t *testing.T) {
 			selector: document.NewSelector().
 				ByGvk("example.com", "v1", "Resource").
 				ByName("stable-resource"),
-			testClient:     makeTestClient(makeResource("Resource", "stable-resource", "stable")),
+			testClient: fake.NewClient(
+				fake.WithDynamicObjects(makeResource("Resource", "stable-resource", "stable")),
+			),
 			expectedStatus: cluster.Status("Stable"),
 		},
 		{
@@ -124,7 +123,9 @@ func TestGetStatusForResource(t *testing.T) {
 			selector: document.NewSelector().
 				ByGvk("example.com", "v1", "Resource").
 				ByName("pending-resource"),
-			testClient:     makeTestClient(makeResource("Resource", "pending-resource", "pending")),
+			testClient: fake.NewClient(
+				fake.WithDynamicObjects(makeResource("Resource", "pending-resource", "pending")),
+			),
 			expectedStatus: cluster.Status("Pending"),
 		},
 		{
@@ -132,7 +133,9 @@ func TestGetStatusForResource(t *testing.T) {
 			selector: document.NewSelector().
 				ByGvk("example.com", "v1", "Resource").
 				ByName("unknown"),
-			testClient:     makeTestClient(makeResource("Resource", "unknown", "unknown")),
+			testClient: fake.NewClient(
+				fake.WithDynamicObjects(makeResource("Resource", "unknown", "unknown")),
+			),
 			expectedStatus: cluster.UnknownStatus,
 		},
 		{
@@ -140,7 +143,9 @@ func TestGetStatusForResource(t *testing.T) {
 			selector: document.NewSelector().
 				ByGvk("example.com", "v1", "Legacy").
 				ByName("stable-legacy"),
-			testClient:     makeTestClient(makeResource("Legacy", "stable-legacy", "stable")),
+			testClient: fake.NewClient(
+				fake.WithDynamicObjects(makeResource("Legacy", "stable-legacy", "stable")),
+			),
 			expectedStatus: cluster.Status("Stable"),
 		},
 		{
@@ -148,7 +153,7 @@ func TestGetStatusForResource(t *testing.T) {
 			selector: document.NewSelector().
 				ByGvk("example.com", "v1", "Missing").
 				ByName("missing-resource"),
-			testClient: makeTestClient(),
+			testClient: fake.NewClient(),
 			err:        cluster.ErrResourceNotFound{Resource: "missing-resource"},
 		},
 	}
@@ -177,15 +182,6 @@ func TestGetStatusForResource(t *testing.T) {
 	}
 }
 
-func makeTestClient(obj ...runtime.Object) fake.Client {
-	testClient := fake.Client{
-		MockDynamicClient: func() dynamic.Interface {
-			return dynamicFake.NewSimpleDynamicClient(runtime.NewScheme(), obj...)
-		},
-	}
-	return testClient
-}
-
 func makeResource(kind, name, state string) *unstructured.Unstructured {
 	return &unstructured.Unstructured{
 		Object: map[string]interface{}{
diff --git a/pkg/k8s/client/client.go b/pkg/k8s/client/client.go
index dd397524d..54e362374 100644
--- a/pkg/k8s/client/client.go
+++ b/pkg/k8s/client/client.go
@@ -28,11 +28,12 @@ import (
 )
 
 // Interface provides an abstraction layer to interactions with kubernetes
-// clusters by providing a ClientSet which includes all kubernetes core objects
-// with standard operations, a DynamicClient which provides interactions with
-// loosely typed kubernetes resources, and a Kubectl interface that is built on
-// top of kubectl libraries and implements such kubectl subcommands as kubectl
-// apply (more will be added)
+// clusters by providing the following:
+// * A ClientSet which includes all kubernetes core objects with standard operations
+// * A DynamicClient which provides interactions with loosely typed kubernetes resources
+// * An ApiextensionsClientSet which provides interactions with CustomResourceDefinitions
+// * A Kubectl interface that is built on top of kubectl libraries and
+//   implements such kubectl subcommands as kubectl apply (more will be added)
 type Interface interface {
 	ClientSet() kubernetes.Interface
 	DynamicClient() dynamic.Interface
@@ -53,8 +54,13 @@ type Client struct {
 // Client implements Interface
 var _ Interface = &Client{}
 
-// NewClient returns Cluster interface with Kubectl
-// and ClientSet interfaces initialized
+// Factory is a function which creates Interfaces
+type Factory func(*environment.AirshipCTLSettings) (Interface, error)
+
+// DefaultClient is a factory which generates a default client
+var DefaultClient Factory = NewClient
+
+// NewClient creates a Client initialized from the passed in settings
 func NewClient(settings *environment.AirshipCTLSettings) (Interface, error) {
 	client := new(Client)
 	var err error
@@ -88,42 +94,42 @@ func NewClient(settings *environment.AirshipCTLSettings) (Interface, error) {
 	return client, nil
 }
 
-// ClientSet getter for ClientSet interface
+// ClientSet returns the ClientSet interface
 func (c *Client) ClientSet() kubernetes.Interface {
 	return c.clientSet
 }
 
-// SetClientSet setter for ClientSet interface
+// SetClientSet sets the ClientSet interface
 func (c *Client) SetClientSet(clientSet kubernetes.Interface) {
 	c.clientSet = clientSet
 }
 
-// DynamicClient getter for DynamicClient interface
+// DynamicClient returns the DynamicClient interface
 func (c *Client) DynamicClient() dynamic.Interface {
 	return c.dynamicClient
 }
 
-// SetDynamicClient setter for DynamicClient interface
+// SetDynamicClient sets the DynamicClient interface
 func (c *Client) SetDynamicClient(dynamicClient dynamic.Interface) {
 	c.dynamicClient = dynamicClient
 }
 
-// ApiextensionsV1 getter for ApiextensionsV1 interface
+// ApiextensionsClientSet returns the Apiextensions interface
 func (c *Client) ApiextensionsClientSet() apix.Interface {
 	return c.apixClient
 }
 
-// SetApiextensionsV1 setter for ApiextensionsV1 interface
+// SetApiextensionsClientSet sets the ApiextensionsClientSet interface
 func (c *Client) SetApiextensionsClientSet(apixClient apix.Interface) {
 	c.apixClient = apixClient
 }
 
-// Kubectl getter for Kubectl interface
+// Kubectl returns the Kubectl interface
 func (c *Client) Kubectl() kubectl.Interface {
 	return c.kubectl
 }
 
-// SetKubectl setter for Kubectl interface
+// SetKubectl sets the Kubectl interface
 func (c *Client) SetKubectl(kctl kubectl.Interface) {
 	c.kubectl = kctl
 }
diff --git a/pkg/k8s/client/client_test.go b/pkg/k8s/client/client_test.go
index 600177ff3..401eda7c0 100644
--- a/pkg/k8s/client/client_test.go
+++ b/pkg/k8s/client/client_test.go
@@ -51,5 +51,7 @@ func TestNewClient(t *testing.T) {
 	assert.NoError(t, err)
 	assert.NotNil(t, client)
 	assert.NotNil(t, client.ClientSet())
+	assert.NotNil(t, client.DynamicClient())
+	assert.NotNil(t, client.ApiextensionsClientSet())
 	assert.NotNil(t, client.Kubectl())
 }
diff --git a/pkg/k8s/client/fake/fake.go b/pkg/k8s/client/fake/fake.go
index 92d477b13..25df6bbd3 100644
--- a/pkg/k8s/client/fake/fake.go
+++ b/pkg/k8s/client/fake/fake.go
@@ -16,79 +16,131 @@ package fake
 
 import (
 	apix "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
+	apixFake "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake"
+	"k8s.io/apimachinery/pkg/runtime"
 	"k8s.io/client-go/dynamic"
+	dynamicFake "k8s.io/client-go/dynamic/fake"
 	"k8s.io/client-go/kubernetes"
+	kubernetesFake "k8s.io/client-go/kubernetes/fake"
 
 	"opendev.org/airship/airshipctl/pkg/k8s/client"
 	"opendev.org/airship/airshipctl/pkg/k8s/kubectl"
+	"opendev.org/airship/airshipctl/testutil/k8sutils"
 )
 
 // Client is an implementation of client.Interface meant for testing purposes.
-// Its member methods are intended to be implemented on a case-by-case basis
-// per test. Examples of implementations can be found with each interface
-// method.
 type Client struct {
-	MockClientSet              func() kubernetes.Interface
-	MockDynamicClient          func() dynamic.Interface
-	MockApiextensionsClientSet func() apix.Interface
-	MockKubectl                func() kubectl.Interface
+	mockClientSet              func() kubernetes.Interface
+	mockDynamicClient          func() dynamic.Interface
+	mockApiextensionsClientSet func() apix.Interface
+	mockKubectl                func() kubectl.Interface
 }
 
 var _ client.Interface = &Client{}
 
 // ClientSet is used to get a mocked implementation of a kubernetes clientset.
-// To initialize the mocked clientset to be returned, the MockClientSet method
-// must be implemented, ideally returning a k8s.io/client-go/kubernetes/fake.Clientset.
-//
-// Example:
-//
-// testClient := fake.Client {
-// 	MockClientSet: func() kubernetes.Interface {
-// 		return kubernetes_fake.NewSimpleClientset()
-// 	},
-// }
-func (c Client) ClientSet() kubernetes.Interface {
-	return c.MockClientSet()
+// To initialize the mocked clientset to be returned, use the WithTypedObjects
+// ResourceAccumulator
+func (c *Client) ClientSet() kubernetes.Interface {
+	return c.mockClientSet()
 }
 
 // DynamicClient is used to get a mocked implementation of a dynamic client.
-// To initialize the mocked client to be returned, the MockDynamicClient method
-// must be implemented, ideally returning a k8s.io/client-go/dynamic/fake.FakeDynamicClient.
-//
-// Example:
-// Here, scheme is a k8s.io/apimachinery/pkg/runtime.Scheme, possibly created
-// via runtime.NewScheme()
-//
-// testClient := fake.Client {
-// 	MockDynamicClient: func() dynamic.Interface {
-// 		return dynamic_fake.NewSimpleDynamicClient(scheme)
-// 	},
-// }
-func (c Client) DynamicClient() dynamic.Interface {
-	return c.MockDynamicClient()
+// To initialize the mocked client to be returned, use the WithDynamicObjects
+// ResourceAccumulator.
+func (c *Client) DynamicClient() dynamic.Interface {
+	return c.mockDynamicClient()
 }
 
 // ApiextensionsClientSet is used to get a mocked implementation of an
-// Apiextensions clientset.  To initialize the mocked client to be returned,
-// the MockApiextensionsClientSet method must be implemented, ideally returning a
-// k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake.ClientSet.
-//
-// Example:
-//
-// testClient := fake.Client {
-// 	MockApiextensionsClientSet: func() apix.Interface {
-// 		return apix_fake.NewSimpleClientset()
-// 	},
-// }
-func (c Client) ApiextensionsClientSet() apix.Interface {
-	return c.MockApiextensionsClientSet()
+// Apiextensions clientset. To initialize the mocked client to be returned,
+// use the WithCRDs ResourceAccumulator
+func (c *Client) ApiextensionsClientSet() apix.Interface {
+	return c.mockApiextensionsClientSet()
 }
 
 // Kubectl is used to get a mocked implementation of a Kubectl client.
-// To initialize the mocked client to be returned, the MockKubectl method
-// must be implemented.
-//
-// Example: TODO(howell)
-func (c Client) Kubectl() kubectl.Interface {
-	return c.MockKubectl()
+// To initialize the mocked client to be returned, use the WithKubectl ResourceAccumulator
+func (c *Client) Kubectl() kubectl.Interface {
+	return c.mockKubectl()
+}
+
+// A ResourceAccumulator is an option meant to be passed to NewClient.
+// ResourceAccumulators can be mixed and matched to create a collection of
+// mocked clients, each having their own fake objects.
+type ResourceAccumulator func(*Client)
+
+// NewClient creates an instance of a Client. If no arguments are passed, the
+// returned Client will have fresh mocked kubernetes clients which will have no
+// prior knowledge of any resources.
+//
+// If prior knowledge of resources is desirable, NewClient should receive an
+// appropriate ResourceAccumulator initialized with the desired resources.
+func NewClient(resourceAccumulators ...ResourceAccumulator) *Client {
+	fakeClient := new(Client)
+	for _, accumulator := range resourceAccumulators {
+		accumulator(fakeClient)
+	}
+
+	if fakeClient.mockClientSet == nil {
+		fakeClient.mockClientSet = func() kubernetes.Interface {
+			return kubernetesFake.NewSimpleClientset()
+		}
+	}
+	if fakeClient.mockDynamicClient == nil {
+		fakeClient.mockDynamicClient = func() dynamic.Interface {
+			return dynamicFake.NewSimpleDynamicClient(runtime.NewScheme())
+		}
+	}
+	if fakeClient.mockApiextensionsClientSet == nil {
+		fakeClient.mockApiextensionsClientSet = func() apix.Interface {
+			return apixFake.NewSimpleClientset()
+		}
+	}
+	if fakeClient.mockKubectl == nil {
+		fakeClient.mockKubectl = func() kubectl.Interface {
+			return kubectl.NewKubectl(k8sutils.NewMockKubectlFactory())
+		}
+	}
+	return fakeClient
+}
+
+// WithTypedObjects returns a ResourceAccumulator with resources which would
+// normally be accessible through a kubernetes ClientSet (e.g. Pods,
+// Deployments, etc...).
+func WithTypedObjects(objs ...runtime.Object) ResourceAccumulator {
+	return func(c *Client) {
+		c.mockClientSet = func() kubernetes.Interface {
+			return kubernetesFake.NewSimpleClientset(objs...)
+		}
+	}
+}
+
+// WithCRDs returns a ResourceAccumulator with resources which would
+// normally be accessible through a kubernetes ApiextensionsClientSet (e.g. CRDs).
+func WithCRDs(objs ...runtime.Object) ResourceAccumulator {
+	return func(c *Client) {
+		c.mockApiextensionsClientSet = func() apix.Interface {
+			return apixFake.NewSimpleClientset(objs...)
+		}
+	}
+}
+
+// WithDynamicObjects returns a ResourceAccumulator with resources which would
+// normally be accessible through a kubernetes DynamicClient (e.g. unstructured.Unstructured).
+func WithDynamicObjects(objs ...runtime.Object) ResourceAccumulator {
+	return func(c *Client) {
+		c.mockDynamicClient = func() dynamic.Interface {
+			return dynamicFake.NewSimpleDynamicClient(runtime.NewScheme(), objs...)
+		}
+	}
+}
+
+// WithKubectl returns a ResourceAccumulator with an instance of a kubectl.Interface.
+func WithKubectl(kubectlInstance *kubectl.Kubectl) ResourceAccumulator {
+	return func(c *Client) {
+		c.mockKubectl = func() kubectl.Interface {
+			return kubectlInstance
+		}
+	}
 }