PrimebrickPrimebrick
  • Primebrick.dev
  • GitHub
  • Documentation
  • Services
  • Libraries
  • API Catalog
Resources
  • Landing Page
  • API Catalog
  • GitHub
PrimebrickPrimebrick

© 2026 Primebrick. MIT License.

github
DAL Library
SDK Library
    Architecture: Ports & AdaptersBuild, Tooling & CI/CDCI/CD & NPM PublishingConfiguration ManagementCore ModulesDatabase MigrationsEnvironment ValidationGetting StartedGlossaryHTTP Server & Health ChecksLifecycle & Graceful ShutdownModule Test PatternsNATS Messaging ClientOverviewService Registration & HeartbeatTest Infrastructure & ConfigurationTestingTypeScript Build ConfigurationREADME
powered by Zudoku
SDK Library

Module Test Patterns

Module Test Patterns

Relevant source files

The following files were used as context for generating this wiki page:

  • src/config/tests/config-loader.test.ts
  • src/env/tests/env-validator.test.ts
  • src/http/tests/http-server.test.ts
  • src/lifecycle/tests/graceful-shutdown.test.ts
  • src/migrations/tests/apply-patches.test.ts
  • src/nats/tests/nats-client.test.ts
  • src/service/tests/service-registrar.test.ts

The @primebrick/sdk employs a testing strategy focused on isolation, portability, and high-fidelity simulation of external dependencies. By leveraging the hexagonal architecture (Ports & Adapters), the SDK ensures that core logic remains testable without requiring a live database or network connection, while integration-level tests verify real HTTP and process-level behaviors.

Port Isolation via Mock Adapters

The primary pattern for testing business logic in the Config, Service, and Migrations modules is the use of in-memory mock adapters for their respective ports. This allows for precise control over the data returned to the SDK and the verification of side effects.

Config & Service Repository Mocks

The ConfigLoader and ServiceRegistrar are tested using factory functions that generate mock implementations of ConfigRepositoryPort and ServiceRegistryPort.

  • makeRepo (Config): Creates a mock that returns a predefined set of configuration rows src/config/tests/config-loader.test.ts:5-9.
  • makeRepo (Service): Creates a mock using vi.fn() to track calls to insert, updateByCode, and findByCode src/service/tests/service-registrar.test.ts:6-16.

Database Port Mock

The Migrations module requires a more sophisticated mock to simulate transaction blocks and query tracking. The makeDb utility captures every SQL statement and parameter sent to the adapter src/migrations/tests/apply-patches.test.ts:10-23.

Data Flow: Mock Adapter Pattern

ComponentPort Mock ImplementationVerification Strategy
ConfigLoaderReturns static array of { key, value } src/config/tests/config-loader.test.ts:15-19Assert getTyped converts types correctly src/config/tests/config-loader.test.ts:50-53
ServiceRegistrarvi.fn() for CRUD operations src/service/tests/service-registrar.test.ts:11-15Assert insert vs update based on findByCode result src/service/tests/service-registrar.test.ts:33-58
MigrationsTracks SQL strings in a calls array src/migrations/tests/apply-patches.test.ts:13-17Verify BEGIN and COMMIT wrap the DDL execution src/migrations/tests/apply-patches.test.ts:57-61

Sources: src/config/tests/config-loader.test.ts:5-20, src/service/tests/service-registrar.test.ts:6-31, src/migrations/tests/apply-patches.test.ts:10-23

Filesystem & Environment Fixtures

Modules that interact with the environment or the local disk use temporary fixtures and process state management to ensure test idempotency.

Temporary Patch Directories

To test applyPatches, the test suite creates a unique temporary directory for each test case using mkdtempSync src/migrations/tests/apply-patches.test.ts:28-30. This directory is populated with .sql files to simulate different migration scenarios (new patches, duplicate SHAs, or modified content) and is recursively deleted after each test src/migrations/tests/apply-patches.test.ts:31-33.

Environment Isolation

The env module tests preserve the original process.env by cloning it before each test and restoring it afterward src/env/tests/env-validator.test.ts:5-13. This prevents cross-test contamination when validating required variables or default values.

Code Entity Space: Migration Test Setup

Code
graph TD subgraph "Test Execution" A["apply-patches.test.ts"] --> B["mkdtempSync"] B --> C["Temporary Directory"] C --> D["writeFileSync(0001_init.sql)"] end subgraph "SDK Logic" E["applyPatches()"] --> F["fs.readdirSync"] F --> C E --> G["DatabasePort.query()"] end G --> H["makeDb Mock"] H -- "Capture SQL" --> I["calls: Array"]

Sources: src/migrations/tests/apply-patches.test.ts:25-61, src/env/tests/env-validator.test.ts:1-13

Singleton & Lifecycle Patterns

Testing global state and process-level events requires specialized mocking of Node.js internals.

NatsClient Singleton Reset

The NatsClient is a singleton. To test its lazy-connection logic, the test suite invokes a private-access style close() method in beforeEach to nullify the internal connection reference src/nats/tests/nats-client.test.ts:16-20. The nats module itself is mocked using vi.mock to return a fake connection object src/nats/tests/nats-client.test.ts:4-10.

GracefulShutdown Process Mocking

Testing GracefulShutdown requires preventing the test runner from actually exiting.

  1. process.exit: Spied on and mocked to throw a specific __EXIT__ error, which is then caught by the test's expectation src/lifecycle/tests/graceful-shutdown.test.ts:9-11.
  2. Signal Handlers: process.on is spied on to verify that SIGTERM, SIGINT, and uncaughtException handlers are correctly registered during install() src/lifecycle/tests/graceful-shutdown.test.ts:47-56.

Sources: src/nats/tests/nats-client.test.ts:1-20, src/lifecycle/tests/graceful-shutdown.test.ts:4-57

Integration: Real HTTP Binding

Unlike other modules, the HttpServer tests perform a "black-box" integration test by binding to a real network port.

Dynamic Port Assignment

To avoid port conflicts during parallel test execution, the server is configured to bind to port 0 src/http/tests/http-server.test.ts:19. The OS assigns a random free port, which is then retrieved via server.address() for use in test requests src/http/tests/http-server.test.ts:23-24.

HealthCheck Verification

The HttpServer test wires a real HealthCheck instance to a mocked HealthCheckPort src/http/tests/http-server.test.ts:20-21. This allows testing the full HTTP lifecycle:

  1. Mock HealthCheckPort.ping returns true.
  2. Test performs fetch() against http://127.0.0.1:{port}/health src/http/tests/http-server.test.ts:32.
  3. Asserts 200 OK and JSON body status: "healthy" src/http/tests/http-server.test.ts:33-36.

Code Entity Space: HTTP Test Lifecycle

Code
sequenceDiagram participant T as "http-server.test.ts" participant S as "HttpServer (http.ts)" participant H as "HealthCheck (health.ts)" participant M as "HealthCheckPort (Mock)" T->>S: createHttpServer({ port: 0 }) S-->>T: Server Instance (Port: 49152) T->>T: fetch("http://localhost:49152/health") T->>S: HTTP GET /health S->>H: runAll() H->>M: ping() M-->>H: true H-->>S: { status: "healthy" } S-->>T: 200 OK { "status": "healthy" }

Sources: src/http/tests/http-server.test.ts:13-43, src/http/tests/http-server.test.ts:67-101


Last modified on July 13, 2026
Lifecycle & Graceful ShutdownNATS Messaging Client
On this page
  • Port Isolation via Mock Adapters
    • Config & Service Repository Mocks
    • Database Port Mock
  • Filesystem & Environment Fixtures
    • Temporary Patch Directories
    • Environment Isolation
  • Singleton & Lifecycle Patterns
    • NatsClient Singleton Reset
    • GracefulShutdown Process Mocking
  • Integration: Real HTTP Binding
    • Dynamic Port Assignment
    • HealthCheck Verification