Skip to content

Mock Servers for API Testing

DodaTech Updated 2026-06-28 3 min read

In this tutorial, you will learn about Mock Servers for API Testing. We cover key concepts, practical examples, and best practices to help you master this topic.

Mock servers simulate API behavior for testing without real backends. WireMock and Pretender provide HTTP mock servers with request matching, response templating, and stateful behavior. They enable isolated testing of services with external dependencies.

What You'll Learn

  • WireMock stub mapping and verification
  • Pretender for browser-side mocking
  • Request matching by URL, headers, body
  • Response templating with dynamic data
  • Record-playback patterns

Why It Matters

Mock servers decouple tests from external dependencies. They make tests faster, more reliable, and able to simulate edge cases that are hard to reproduce with real services.

Real-World Use

WireMock is used by Spring Boot projects for integration tests. Pretender is used in Ember.js testing. Many microservice test suites use WireMock for dependency isolation.

flowchart LR
    Test[Integration Test] --> Service[Service Under Test]
    Service --> Mock[Mock Server]
    Mock --> Stub[Stub Mapping]
    Mock --> Matcher[Request Matching]
    Mock --> Response[Response Generation]
    Mock --> Verify[Verification]

Teacher Mindset

Mock servers replace real dependencies in tests. Define stubs for expected requests. Verify that the expected requests were made. Use response templating for dynamic data.

Code Examples

// Example 1: WireMock stub definition
import static com.github.tomakehurst.wiremock.client.WireMock.*;

@Test
public void testGetUser() {
    stubFor(get(urlEqualTo("/api/users/1"))
        .willReturn(aResponse()
            .withStatus(200)
            .withHeader("Content-Type", "application/json")
            .withBody("{\"id\":1,\"name\":\"Alice\",\"email\":\"alice@test.com\"}")));

    // Service under test calls http://localhost:8080/api/users/1
    User user = userService.getUser(1);
    assertThat(user.getName()).isEqualTo("Alice");
}
// Example 2: WireMock with request matching and verification
@Test
public void testCreateUser() {
    stubFor(post(urlEqualTo("/api/users"))
        .withRequestBody(matchingJsonPath("$.name"))
        .withRequestBody(matchingJsonPath("$.email"))
        .willReturn(aResponse()
            .withStatus(201)
            .withBody("{\"id\":2,\"name\":\"Bob\"}")));

    userService.createUser("Bob", "bob@test.com");

    verify(postRequestedFor(urlEqualTo("/api/users"))
        .withRequestBody(containing("Bob")));
}
// Example 3: Pretender for browser mocking
import Pretender from 'pretender';

const server = new Pretender();

server.get('/api/users', () => {
  return [200, { 'Content-Type': 'application/json' },
    JSON.stringify({ users: [
      { id: 1, name: 'Alice' },
      { id: 2, name: 'Bob' }
    ]})
  ];
});

server.post('/api/users', (request) => {
  const body = JSON.parse(request.requestBody);
  return [201, { 'Content-Type': 'application/json' },
    JSON.stringify({ id: 3, name: body.name })
  ];
});

// After test
server.shutdown();

Common Mistakes

  • Making mocks too complex, testing the mock instead of the system
  • Not verifying that expected requests were actually made
  • Using mocks for services where contract tests are more appropriate
  • Hardcoding response data instead of using response templating
  • Forgetting to reset mock state between tests

Practice

  1. Create a WireMock stub for a GET endpoint with JSON response.
  2. Add request matching by header and query parameter.
  3. Use response templating to return dynamic IDs.
  4. Verify that the service made the expected requests.
  5. Challenge: Implement a stateful mock that returns different responses on subsequent calls.

FAQ

What is the difference between mocking and stubbing?

Stubbing defines canned responses. Mocking adds expectations and verification. WireMock supports both.

Can WireMock work over HTTPS?

Yes. WireMock supports SSL/TLS for HTTPS testing.

How do I reset WireMock between tests?

Call WireMock.reset() in your test teardown to clear all stubs and request logs.

What is record-playback mode?

WireMock records real API calls and replays them in tests. Useful for creating mocks from actual API behavior.

Can I use Pretender in Node.js tests?

Pretender is designed for browser testing. For Node.js, use nock or mockttp for HTTP mocking.

Mini Project

Set up a WireMock server for an external payment API. Create stubs for successful payment, declined card, insufficient funds, and timeout scenarios. Write integration tests that use each stub and verify the system behavior.

What's Next

Next, you will learn about generating test data with Faker for realistic API tests.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro