Skip to main content

OpraTestClient

OpraTestClient is a test-specific HTTP client that sends requests directly to your application handler without binding a port. There is no server to start or stop between tests; the client closes the connection after each request.

Constructor​

import { OpraTestClient } from '@opra/testing';

const testClient = new OpraTestClient(app, options?);
ParameterTypeDescription
appServer | RequestListenerThe HTTP server or (req, res) => void handler to test
optionsOpraTestClient.OptionsOptional. Extends FetchBackend.Options with an optional basePath

Making requests​

Every HTTP method returns an HttpRequestObservable. Call .getResponse() to resolve it and get back an HttpResponse with an .expect property pre-attached.

const res = await testClient.get('/customers').getResponse();
const res = await testClient.post('/customers', body).getResponse();
const res = await testClient.patch('/customers@42', body).getResponse();
const res = await testClient.delete('/customers@42').getResponse();

Chain .param() and .header() before .getResponse():

const res = await testClient
.get('/customers')
.param({ limit: 10, sort: ['familyName'] })
.header('X-Tenant-Id', tenantId)
.getResponse();

Setup pattern​

Initialise a single TestApp instance per describe block and tear it down afterwards:

import { OpraTestClient } from '@opra/testing';
import { TestApp } from '#test-app';

describe('e2e: /Customers', () => {
let testApp: TestApp;
let testClient: OpraTestClient;

before(async () => {
testApp = await TestApp.create();
testClient = testApp.client;
});
after(() => testApp?.close());
beforeEach(() => testApp?.restoreUser());
afterEach(() => testApp?.restoreUser());
});

TestApp is a thin wrapper your project owns — it boots the application, exposes client and moduleRef, and provides helpers like restoreUser() to reset per-test state.

Testing authentication​

Set testApp.user._id to an empty string to simulate an unauthenticated (anonymous) request:

it('Should reject anonymous requests', async () => {
testApp.user._id = '';
const res = await testClient.get('/organizations').getResponse();
res.expect.toFail(HttpStatusCode.UNAUTHORIZED);
});

Testing authorization​

Set testApp.user.roles to control which roles are active:

it('Should permit SUPPORT_USER', async () => {
testApp.user.roles = [UserRole.SUPPORT_USER];
const res = await testClient.get('/organizations').getResponse();
res.expect.toSuccess(HttpStatusCode.OK).toReturnCollection();
});

it('Should forbid ORGANIZATION_OWNER', async () => {
testApp.user.roles = [UserRole.ORGANIZATION_OWNER];
const res = await testClient.get('/organizations').getResponse();
res.expect.toFail(HttpStatusCode.FORBIDDEN);
});

testApp.restoreUser() — called in beforeEach and afterEach — resets user state so tests do not leak into each other.