Skip to content

guides‐testing

github-actions[bot] edited this page Oct 6, 2024 · 7 revisions

Guides: Testing

There are many ways to configure Zimic in a testing environment. Usually, the best approach is dependent on your method of intercepting requests and how you are applying your mocks.

  • Local HTTP interceptors are the simplest to use in tests, as they do not require any server setup and apply mocks to the process they are running in. Because of that, you generally do not need to worry about concurrency problems and racing conditions between test workers. This is valid in both client-side and server-side environments.
  • Remote HTTP interceptors are more complex to set up and require an interceptor server to handle requests. They are generally used in end-to-end tests, where the test runner and the application run in separate processes. In this case, you do need to manage concurrency and racing conditions between test workers. This can be done by either:
    1. Applying your mocks to the interceptor server before your application and tests start. See Next.js App Router - Loading mocks and Playwright - Loading mocks as examples.
    2. Using a path discriminator when creating interceptors in your test workers.

If you are creating mocks during your tests, you can manage the lifecycle of your interceptors in your test setup file, using beforeAll/beforeEach/afterEach/afterAll or equivalent hooks.

An example using a Jest/Vitest API:

tests/setup.ts

Using local interceptors
// Your interceptors
import myInterceptor from './interceptors/myInterceptor';
import myOtherInterceptor from './interceptors/myOtherInterceptor';

// Start intercepting requests
beforeAll(async () => {
  await myInterceptor.start();
  await myOtherInterceptor.start();
});

// Clear interceptors so that no tests affect each other
afterEach(() => {
  myInterceptor.clear();
  myOtherInterceptor.clear();
});

// Stop intercepting requests
afterAll(async () => {
  await myInterceptor.stop();
  await myOtherInterceptor.stop();
});
Using remote interceptors
// Your interceptors
import myInterceptor from './interceptors/myInterceptor';
import myOtherInterceptor from './interceptors/myOtherInterceptor';

// Start intercepting requests
beforeAll(async () => {
  await myInterceptor.start();
  await myOtherInterceptor.start();
});

// Clear all interceptors so that no tests affect each other
afterEach(async () => {
  // Important: clearing remote interceptors is asynchronous
  await myInterceptor.clear();
  await myOtherInterceptor.clear();
});

// Stop intercepting requests
afterAll(async () => {
  await myInterceptor.stop();
  await myOtherInterceptor.stop();
});