@stratal/testing
Test utilities for Stratal applications: module compilation with provider overrides, fluent HTTP client, storage fakes, fetch mocking, and auth testing helpers. Full documentation at stratal.dev/testing.
Setup
Docs: Overview
// vitest.setup.ts import 'reflect-metadata'; import { Test } from '@stratal/testing'; Test.setBaseModules([CoreModule]);
Test file convention: src//tests//*.spec.ts . Always call module.close() in afterEach .
Creating Test Modules
Docs: Testing Module
const module = await Test.createTestingModule({ imports: [UsersModule], }) .overrideProvider(EMAIL_TOKEN) .useValue(mockEmailService) .withEnv({ DATABASE_URL: 'test-url' }) .compile();
Access services: module.get(TOKEN) . Access HTTP client: module.http . Access container: module.container .
Provider Overrides
Chain overrides before .compile() :
Test.createTestingModule({ imports: [AppModule] }) .overrideProvider(TOKEN_A).useValue(mockA) .overrideProvider(TOKEN_B).useClass(FakeB) .overrideProvider(TOKEN_C).useFactory(() => stub) .compile();
Use .withEnv() to set environment variables. Use Test.setBaseModules() for modules shared across all tests.
HTTP Testing
Docs: HTTP Testing
const response = await module.http .post('/api/v1/users') .withBody({ email: 'test@example.com' }) .withHeaders({ 'X-Custom': 'value' }) .send();
response.assertCreated(); await response.assertJsonPath('data.email', 'test@example.com');
Assertion methods: assertOk() , assertCreated() , assertNotFound() , assertUnauthorized() , assertForbidden() , assertStatus(code) , assertJsonPath(path, value) , assertJsonStructure(shape) .
FakeStorageService
Docs: Mocks & Fakes
Auto-registered in test modules. Access via module.storage . Assertions: assertExists(path) , assertMissing(path) , assertEmpty() , assertCount(n) . Utility: getStoredPaths() , getFile(path) , clear() .
Fetch Mocking
Docs: Mocks & Fakes
import { createFetchMock } from '@stratal/testing';
const mock = createFetchMock(); // In beforeEach: mock.activate(); mock.disableNetConnect() // In afterEach: mock.reset()
mock.mockJsonResponse('https://api.example.com/data', { result: 'ok' }); mock.mockError('https://api.example.com/fail', 503, 'Service Unavailable');
Deep Mocks
Docs: Mocks & Fakes
import { createMock } from '@stratal/testing/mocks';
const mockEmailService = createMock<EmailService>(); mockEmailService.send.mockResolvedValueOnce(undefined);
Use with overrideProvider(TOKEN).useValue(mockEmailService) .
Auth Testing (ActingAs)
import { ActingAs } from '@stratal/testing';
const actingAs = new ActingAs(module.get(AUTH_SERVICE)); const headers = await actingAs.createSessionForUser({ id: 'user-1' }); const response = await module.http .withHeaders(headers) .get('/api/v1/profile') .send();
Database Testing
// Truncate tables between tests await module.truncateDb();
// Seed test data await module.seed(new UserSeeder());
// Database assertions await module.assertDatabaseHas('user', { email: 'test@example.com' }); await module.assertDatabaseMissing('user', { email: 'deleted@example.com' }); await module.assertDatabaseCount('user', 5);
Test Patterns
-
Create module in beforeEach , call module.close() in afterEach
-
Override external services (email, storage, external APIs) with mocks/fakes
-
Use module.runInRequestScope() to test request-scoped services
-
Use factories for test data, seeders for complex test setup
-
Assert HTTP responses with fluent assertion chains
-
Use module.getDb() for direct database access in tests