A JUnit 5 testing library that provides a Kubernetes mock server for testing Kubernetes client applications
—
Automatic mock server setup and teardown for JUnit 5 tests with annotation-based configuration. Handles both static and instance field injection.
Primary annotation for enabling automatic Kubernetes mock client setup in JUnit 5 tests.
/**
* Annotation for enabling KubernetesMockServerExtension JUnit5 extension
* Automatically sets up mock server and injects client instances
*/
@Target({ TYPE, METHOD, ANNOTATION_TYPE })
@Retention(RUNTIME)
@ExtendWith(KubernetesMockServerExtension.class)
public @interface EnableKubernetesMockClient {
/**
* Enable HTTPS for the mock server
* @return true to use HTTPS, false for HTTP
*/
boolean https() default true;
/**
* Enable CRUD mode for the mock server
* When true, provides full in-memory Kubernetes API
* When false, uses expectations-based mocking
* @return true for CRUD mode, false for expectations mode
*/
boolean crud() default false;
/**
* Custom builder customizer for the KubernetesClient
* Must have a no-argument constructor
* @return Class implementing Consumer<KubernetesClientBuilder>
*/
Class<? extends Consumer<KubernetesClientBuilder>> kubernetesClientBuilderCustomizer()
default KubernetesClientBuilderCustomizer.class;
}Usage Examples:
// Basic setup with defaults (HTTPS, expectations mode)
@EnableKubernetesMockClient
class BasicTest {
KubernetesMockServer server;
KubernetesClient client;
}
// CRUD mode with HTTPS
@EnableKubernetesMockClient(crud = true)
class CrudTest {
KubernetesMockServer server;
KubernetesClient client;
}
// HTTP-only expectations mode
@EnableKubernetesMockClient(https = false)
class HttpTest {
KubernetesMockServer server;
KubernetesClient client;
}
// Custom client configuration
@EnableKubernetesMockClient(
crud = true,
kubernetesClientBuilderCustomizer = MyCustomizer.class
)
class CustomTest {
KubernetesMockServer server;
KubernetesClient client;
public static class MyCustomizer implements Consumer<KubernetesClientBuilder> {
public MyCustomizer() {} // Required no-arg constructor
@Override
public void accept(KubernetesClientBuilder builder) {
builder.withRequestTimeout(60000)
.withNamespace("custom-namespace");
}
}
}JUnit 5 extension that handles the lifecycle of mock servers and client injection.
/**
* JUnit 5 extension implementation for automatic mock server setup
* Handles both static and instance field injection
*/
public class KubernetesMockServerExtension
implements AfterEachCallback, AfterAllCallback, BeforeEachCallback, BeforeAllCallback {
/**
* Called before each test method
* Sets up instance-level mock server and client
* @param context JUnit extension context
*/
public void beforeEach(ExtensionContext context) throws Exception;
/**
* Called after each test method
* Cleans up instance-level resources
* @param context JUnit extension context
*/
public void afterEach(ExtensionContext context);
/**
* Called before all test methods in a class
* Sets up static mock server and client if needed
* @param context JUnit extension context
*/
public void beforeAll(ExtensionContext context) throws Exception;
/**
* Called after all test methods in a class
* Cleans up static resources
* @param context JUnit extension context
*/
public void afterAll(ExtensionContext context);
}The extension automatically injects appropriate instances into test class fields based on their types and modifiers.
Supported Field Types:
// Mock server injection
KubernetesMockServer server; // Instance field
static KubernetesMockServer server; // Static field
// Client injection - any of these types work
KubernetesClient client;
NamespacedKubernetesClient client;
Client client; // Base client interface
// Static client injection
static KubernetesClient client;
static NamespacedKubernetesClient client;Field Injection Rules:
Usage Examples:
@EnableKubernetesMockClient
class FieldInjectionTest {
// These fields will be automatically injected
KubernetesMockServer server;
KubernetesClient client;
@Test
void testWithInjectedFields() {
// server and client are ready to use
assertNotNull(server);
assertNotNull(client);
// Set up expectations
server.expect().get()
.withPath("/api/v1/namespaces")
.andReturn(200, new NamespaceListBuilder().build())
.once();
// Use client
NamespaceList namespaces = client.namespaces().list();
assertNotNull(namespaces);
}
}
@EnableKubernetesMockClient(crud = true)
class StaticFieldTest {
// Static fields shared across all test methods
static KubernetesMockServer server;
static KubernetesClient client;
@Test
void testOne() {
// Use shared server and client
Pod pod = new PodBuilder().withNewMetadata().withName("test1").endMetadata().build();
client.pods().inNamespace("default").resource(pod).create();
}
@Test
void testTwo() {
// Same server instance, data persists from previous test
Pod retrieved = client.pods().inNamespace("default").withName("test1").get();
assertNotNull(retrieved);
}
}Interface for customizing the KubernetesClientBuilder used by the extension.
/**
* Default customizer that applies no additional configuration
*/
public class KubernetesClientBuilderCustomizer implements Consumer<KubernetesClientBuilder> {
public KubernetesClientBuilderCustomizer();
@Override
public void accept(KubernetesClientBuilder kubernetesClientBuilder);
}
// Custom customizer example
public class MyCustomizer implements Consumer<KubernetesClientBuilder> {
public MyCustomizer() {} // Required no-arg constructor
@Override
public void accept(KubernetesClientBuilder builder) {
builder.withRequestTimeout(30000)
.withConnectionTimeout(5000)
.withNamespace("my-namespace")
.withTrustCerts(false);
}
}Usage Examples:
@EnableKubernetesMockClient(kubernetesClientBuilderCustomizer = TimeoutCustomizer.class)
class CustomizedClientTest {
KubernetesMockServer server;
KubernetesClient client; // Will have custom timeouts applied
public static class TimeoutCustomizer implements Consumer<KubernetesClientBuilder> {
public TimeoutCustomizer() {}
@Override
public void accept(KubernetesClientBuilder builder) {
builder.withRequestTimeout(60000)
.withConnectionTimeout(15000);
}
}
}
// Customizer with additional HTTP client configuration
public static class HttpCustomizer implements Consumer<KubernetesClientBuilder> {
public HttpCustomizer() {}
@Override
public void accept(KubernetesClientBuilder builder) {
builder.withHttpClientFactory(new CustomHttpClientFactory())
.withUserAgent("MyTestAgent/1.0");
}
}The extension automatically manages the complete lifecycle of mock servers and clients:
Before Each Test:
KubernetesMockServer instance based on annotation configurationKubernetesClient using configured customizerAfter Each Test:
Static Lifecycle:
Install with Tessl CLI
npx tessl i tessl/maven-io-fabric8--kubernetes-server-mock