WireMock is a comprehensive API mocking and service virtualization library for testing and development environments with HTTP server simulation capabilities.
Seamless integration with JUnit 4 and JUnit 5 testing frameworks providing lifecycle management, parameter injection, and declarative configuration for comprehensive test automation with WireMock.
Complete JUnit 4 support with test rules for method-level and class-level server lifecycle management.
/**
* JUnit 4 test rule for method-level server lifecycle
*/
class WireMockRule extends WireMockServer implements TestRule {
// Constructors
/** Default constructor with dynamic port */
WireMockRule();
/** Constructor with specific HTTP port */
WireMockRule(int port);
/** Constructor with HTTP and HTTPS ports */
WireMockRule(int port, Integer httpsPort);
/** Constructor with custom options */
WireMockRule(Options options);
/** Constructor with options and failure behavior */
WireMockRule(Options options, boolean failOnUnmatchedRequests);
// TestRule Implementation
Statement apply(Statement base, Description description);
// Lifecycle Hooks (protected)
/** Called before each test method */
protected void before();
/** Called after each test method */
protected void after();
}
/**
* JUnit 4 class rule for class-level server lifecycle
*/
class WireMockClassRule extends WireMockServer implements MethodRule, TestRule {
// Constructors (same as WireMockRule)
WireMockClassRule();
WireMockClassRule(int port);
WireMockClassRule(int port, Integer httpsPort);
WireMockClassRule(Options options);
// TestRule Implementation
Statement apply(Statement base, Description description);
// MethodRule Implementation
Statement apply(Statement base, FrameworkMethod method, Object target);
// Lifecycle Hooks
protected void before();
protected void after();
}
/**
* Core stubbing interface for test integration
*/
interface Stubbing {
// Stub Management
void givenThat(MappingBuilder mappingBuilder);
void stubFor(MappingBuilder mappingBuilder);
void editStub(MappingBuilder mappingBuilder);
void removeStub(MappingBuilder mappingBuilder);
void removeStub(StubMapping stubMapping);
void removeStub(UUID id);
// Stub Retrieval
ListStubMappingsResult getStubMappings();
SingleStubMappingResult getSingleStubMapping(UUID id);
ListStubMappingsResult findStubMappingsByMetadata(StringValuePattern pattern);
// Request Verification
void verify(RequestPatternBuilder requestPatternBuilder);
void verify(int count, RequestPatternBuilder requestPatternBuilder);
void verify(CountMatchingStrategy strategy, RequestPatternBuilder requestPatternBuilder);
// Request Inspection
List<LoggedRequest> findAll(RequestPatternBuilder requestPatternBuilder);
List<ServeEvent> getAllServeEvents();
List<LoggedRequest> findAllUnmatchedRequests();
// Near Miss Analysis
List<NearMiss> findNearMissesFor(LoggedRequest loggedRequest);
List<NearMiss> findAllNearMissesFor(RequestPattern requestPattern);
// Global Settings
void setGlobalFixedDelay(int milliseconds);
}Usage Examples:
import com.github.tomakehurst.wiremock.junit.WireMockRule;
import org.junit.Rule;
import org.junit.Test;
import static com.github.tomakehurst.wiremock.client.WireMock.*;
public class MyServiceTest {
@Rule
public WireMockRule wireMockRule = new WireMockRule(8089);
@Test
public void testApiCall() {
// Setup stub
stubFor(get(urlEqualTo("/api/data"))
.willReturn(aResponse()
.withStatus(200)
.withBody("test data")));
// Execute test
String result = myService.fetchData("http://localhost:8089/api/data");
// Verify
assertEquals("test data", result);
verify(getRequestedFor(urlEqualTo("/api/data")));
}
}
// Class-level rule example
public class IntegrationTest {
@ClassRule
public static WireMockClassRule wireMock = new WireMockClassRule(8089);
@Rule
public WireMockClassRule instanceRule = wireMock;
@Test
public void testOne() {
instanceRule.stubFor(get(urlEqualTo("/test1"))
.willReturn(ok()));
}
@Test
public void testTwo() {
instanceRule.stubFor(get(urlEqualTo("/test2"))
.willReturn(ok()));
}
}Modern JUnit Jupiter extension with declarative configuration and parameter injection support.
/**
* JUnit 5 extension for WireMock integration
*/
class WireMockExtension extends DslWrapper implements
ParameterResolver, BeforeEachCallback, BeforeAllCallback,
AfterEachCallback, AfterAllCallback {
// Static Factory Methods
/** Create extension builder */
static Builder newInstance();
/** Alias for newInstance() */
static Builder extensionOptions();
// Lifecycle Callbacks
void beforeAll(ExtensionContext context);
void beforeEach(ExtensionContext context);
void afterEach(ExtensionContext context);
void afterAll(ExtensionContext context);
// Parameter Resolution
boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext);
Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext);
// Extension Hooks (protected)
/** Called before all tests in class */
protected void onBeforeAll(ExtensionContext context);
/** Called before each test method */
protected void onBeforeEach(ExtensionContext context);
/** Called after each test method */
protected void onAfterEach(ExtensionContext context);
/** Called after all tests in class */
protected void onAfterAll(ExtensionContext context);
/**
* Builder for WireMockExtension configuration
*/
static class Builder {
/** Set server options */
Builder options(Options options);
/** Configure static DSL */
Builder configureStaticDsl(boolean configureStaticDsl);
/** Fail on unmatched requests */
Builder failOnUnmatchedRequests(boolean failOnUnmatchedRequests);
/** Enable proxy mode */
Builder proxyMode(boolean proxyMode);
/** Reset server between tests */
Builder resetOnEachTest(boolean resetOnEachTest);
/** Build configured extension */
WireMockExtension build();
}
}
/**
* Declarative annotation for WireMock test configuration
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@ExtendWith(WireMockExtension.class)
public @interface WireMockTest {
/** Enable extension scanning */
boolean extensionScanningEnabled() default false;
/** HTTP port (0 for dynamic) */
int httpPort() default 0;
/** Enable HTTPS */
boolean httpsEnabled() default false;
/** HTTPS port (0 for dynamic) */
int httpsPort() default 0;
/** Enable proxy mode */
boolean proxyMode() default false;
}
/**
* Runtime information about WireMock server for parameter injection
*/
class WireMockRuntimeInfo {
/** Get HTTP port */
int getHttpPort();
/** Get HTTPS port */
int getHttpsPort();
/** Check if HTTP is enabled */
boolean isHttpEnabled();
/** Check if HTTPS is enabled */
boolean isHttpsEnabled();
/** Get HTTP base URL */
String getHttpBaseUrl();
/** Get HTTPS base URL */
String getHttpsBaseUrl();
/** Get configured WireMock client */
WireMock getWireMock();
}Usage Examples:
import com.github.tomakehurst.wiremock.junit5.WireMockExtension;
import com.github.tomakehurst.wiremock.junit5.WireMockTest;
import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import static com.github.tomakehurst.wiremock.client.WireMock.*;
// Declarative configuration
@WireMockTest(httpPort = 8089, httpsEnabled = true)
class DeclarativeTest {
@Test
void testWithRuntimeInfo(WireMockRuntimeInfo wmRuntimeInfo) {
// Setup stub
stubFor(get("/api/test")
.willReturn(ok("Hello World")));
// Use runtime info
String baseUrl = wmRuntimeInfo.getHttpBaseUrl();
assertEquals("http://localhost:8089", baseUrl);
// Execute and verify
String result = callApi(baseUrl + "/api/test");
assertEquals("Hello World", result);
verify(getRequestedFor(urlEqualTo("/api/test")));
}
}
// Programmatic configuration
class ProgrammaticTest {
@RegisterExtension
static WireMockExtension wm = WireMockExtension.newInstance()
.options(wireMockConfig()
.port(8089)
.httpsPort(8443)
.keystorePath("test-keystore.jks"))
.failOnUnmatchedRequests(true)
.build();
@Test
void testWithExtension() {
wm.stubFor(get("/api/secure")
.willReturn(ok("Secure response")));
// Test logic here
wm.verify(getRequestedFor(urlEqualTo("/api/secure")));
}
}
// Per-test lifecycle
class PerTestTest {
@RegisterExtension
WireMockExtension wm = WireMockExtension.newInstance()
.resetOnEachTest(true)
.build();
@Test
void testOne(WireMockRuntimeInfo wmRuntimeInfo) {
wm.stubFor(get("/test1").willReturn(ok()));
// Test automatically resets after this method
}
@Test
void testTwo(WireMockRuntimeInfo wmRuntimeInfo) {
wm.stubFor(get("/test2").willReturn(ok()));
// Previous test's stubs are automatically cleared
}
}Administrative wrapper that combines admin and stubbing functionality for test integration.
/**
* Wrapper combining Admin and Stubbing interfaces for test integration
*/
class DslWrapper implements Admin, Stubbing {
/** Constructor with admin instance */
DslWrapper(Admin admin);
// Delegates to both Admin and Stubbing interfaces
// Includes all methods from:
// - Admin interface (server management, request journal, scenarios)
// - Stubbing interface (stub management, verification, inspection)
// Additional Test Utilities
/** Get server port */
int getPort();
/** Get server options */
Options getOptions();
/** Check if server is running */
boolean isRunning();
/** Get base URL for HTTP */
String baseUrl();
/** Get base URL for HTTPS */
String httpsBaseUrl();
}/**
* @deprecated Legacy static rule - use WireMockClassRule instead
*/
@Deprecated
class WireMockStaticRule implements MethodRule {
WireMockStaticRule();
WireMockStaticRule(int port);
WireMockStaticRule(Options options);
Statement apply(Statement base, FrameworkMethod method, Object target);
}JUnit 4 vs JUnit 5 Decision Matrix:
| Feature | JUnit 4 | JUnit 5 |
|---|---|---|
| Lifecycle Management | @Rule, @ClassRule | @ExtendWith, @WireMockTest |
| Configuration | Constructor parameters | Builder pattern + annotation |
| Parameter Injection | Not supported | WireMockRuntimeInfo injection |
| Declarative Config | Not supported | @WireMockTest annotation |
| Extension Points | Override before()/after() | Override lifecycle callbacks |
| Static DSL Config | Manual | Automatic option |
Usage Recommendations:
// For simple tests - use declarative approach
@WireMockTest
class SimpleTest {
@Test
void test(WireMockRuntimeInfo wmInfo) {
// Test logic with automatic WireMock setup
}
}
// For complex configuration - use programmatic approach
class ComplexTest {
@RegisterExtension
static WireMockExtension wm = WireMockExtension.newInstance()
.options(wireMockConfig()
.port(8089)
.httpsPort(8443)
.extensionScanningEnabled(true)
.extensions("com.example.CustomTransformer"))
.failOnUnmatchedRequests(true)
.build();
}
// For class-level setup with method-level cleanup
class MixedLifecycleTest {
@RegisterExtension
static WireMockExtension wm = WireMockExtension.newInstance()
.resetOnEachTest(false) // Keep stubs across tests
.build();
@BeforeAll
static void setupCommonStubs() {
wm.stubFor(get("/common").willReturn(ok()));
}
@AfterEach
void cleanupTestSpecificStubs() {
// Clean up only test-specific stubs
}
}Install with Tessl CLI
npx tessl i tessl/maven-org-wiremock--wiremock