Spies, Noops & MockHttpClient
In addition to MockHttpAdapter, the testing sub-path ships lower-level helpers for testing specific parts of your pipeline in isolation.
MockHttpClient
A lower-level test double for the HttpClientContract transport layer. Use it when testing custom HttpClient wrappers rather than full adapter pipelines.
It exposes the same queue API and assertion helpers as MockHttpAdapter:
import { MockHttpClient } from '@yildizpay/http-adapter/testing';
const client = new MockHttpClient();
client.mockResolvedValue({ data: { id: 1 }, status: 200, headers: {} });
const result = await client.request(config);
client.assertCalledTimes(1);
client.assertCalledWith({ method: HttpMethod.POST });Noop Helpers
Pass-through implementations that satisfy a contract without any side effects. Useful when a hook must be provided but its behaviour is irrelevant to the test under execution.
| Class | Implements |
|---|---|
NoopInterceptor | All four HttpInterceptor hooks — returns each value unchanged |
NoopObserver | All HttpAdapterObserver hooks — empty methods |
NoopCircuitBreakerObserver | All CircuitBreakerObserver hooks — empty methods |
import {
NoopInterceptor,
NoopObserver,
NoopCircuitBreakerObserver,
} from '@yildizpay/http-adapter/testing';
const adapter = HttpAdapter.builder()
.withInterceptor(new NoopInterceptor())
.withObserver(new NoopObserver())
.build();Spy Helpers
Spy helpers record every invocation and pass values through unchanged. Use them to assert that a hook was called without needing to mock the full request pipeline.
SpyInterceptor
Records calls to all four interceptor hooks:
import { SpyInterceptor } from '@yildizpay/http-adapter/testing';
const interceptorSpy = new SpyInterceptor();
const adapter = HttpAdapter.builder()
.withInterceptor(interceptorSpy)
.build();
await adapter.send(request);
expect(interceptorSpy.requestCalls).toHaveLength(1);
expect(interceptorSpy.responseCalls).toHaveLength(1);
expect(interceptorSpy.errorCalls).toHaveLength(0);
// Reset between tests
interceptorSpy.reset();SpyObserver
Records calls to all observer hooks:
import { SpyObserver } from '@yildizpay/http-adapter/testing';
const observerSpy = new SpyObserver();
const adapter = HttpAdapter.builder()
.withObserver(observerSpy)
.build();
await adapter.send(request);
expect(observerSpy.requestStartCalls).toHaveLength(1);
expect(observerSpy.successCalls[0].durationMs).toBeGreaterThan(0);
expect(observerSpy.failureCalls).toHaveLength(0);
expect(observerSpy.retryCalls).toHaveLength(0);
observerSpy.reset();Recorded Arrays Reference
| Spy | Recorded arrays |
|---|---|
SpyInterceptor | requestCalls, responseCalls, responseValidatedCalls, errorCalls |
SpyObserver | requestStartCalls, successCalls, failureCalls, retryCalls |
Putting It All Together
A common pattern in integration tests: use SpyInterceptor and SpyObserver alongside MockHttpAdapter to assert the full pipeline was exercised correctly.
import {
MockHttpAdapter,
SpyInterceptor,
SpyObserver,
} from '@yildizpay/http-adapter/testing';
const adapter = new MockHttpAdapter();
const interceptorSpy = new SpyInterceptor();
const observerSpy = new SpyObserver();
// Wire spies into a real adapter wrapping the mock transport
const wrappedAdapter = HttpAdapter.builder()
.withHttpClient(adapter) // inject mock transport
.withInterceptor(interceptorSpy)
.withObserver(observerSpy)
.build();
adapter.mockResolvedValue({ id: 'order_1' });
await wrappedAdapter.send(request);
// Verify full pipeline was exercised
expect(interceptorSpy.requestCalls).toHaveLength(1);
expect(interceptorSpy.responseCalls).toHaveLength(1);
expect(observerSpy.successCalls).toHaveLength(1);