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.