npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@speajus/diblob-testing

v1.0.3

Published

Testing utilities and fake infrastructure blobs for diblob containers

Readme

@speajus/diblob-testing

Testing utilities for diblob dependency injection containers.

Overview

@speajus/diblob-testing provides comprehensive testing utilities for applications using the diblob dependency injection framework. It includes test container factories, blob override utilities, fake infrastructure implementations, and seamless integration with Node.js's built-in test runner.

Installation

pnpm add -D @speajus/diblob-testing

Quick Start

import assert from 'node:assert/strict';
import { describe, test } from 'node:test';
import { setupEachTestContainer, testLogger } from '@speajus/diblob-testing';

describe('My Service Tests', () => {
  const { getContainer } = setupEachTestContainer();

  test('should log messages', async () => {
    const container = getContainer();
    const logger = await container.resolve(testLogger);

    logger.info('Test message');

    const records = logger.getRecords();
    assert.strictEqual(records.length, 1);
    assert.strictEqual(records[0].message, 'Test message');
  });
});

Core Features

Test Container Factories

  • createTestContainer(options?) - Creates a container pre-configured with test infrastructure
  • createIsolatedTestContainer(options?) - Creates a container that defaults all registrations to transient lifecycle for better test isolation

Blob Override Utilities

  • withBlobOverride(container, blob, implementation, testFn) - Safely override a blob implementation for a single test, with automatic cleanup

Fake Infrastructure Blobs

  • testLogger - In-memory logger that captures log records for verification
  • testClock - Controllable clock for testing time-dependent code
  • testRandom - Deterministic random number generator for reproducible tests
  • httpClientStub - HTTP client stub with request recording and response queuing
  • httpServerStub - HTTP server stub with configurable request handlers

node:test Integration

  • setupFileScopedTestContainer(options?) - Creates a shared container for all tests in a file
  • setupEachTestContainer(options?) - Creates fresh isolated containers for each test

API Reference

Container Options

interface TestContainerOptions {
  randomSeed?: number;      // Seed for deterministic RNG (default: 42)
  initialTime?: number;     // Initial timestamp for test clock (default: 0)
  includeHttp?: boolean;    // Include HTTP stubs (default: true)
}

Test Infrastructure Examples

Logger Testing

const container = createTestContainer();
const logger = await container.resolve(testLogger);

logger.info('Hello', { user: 'test' });
logger.error('Oops');

const records = logger.getRecords();
// Verify log messages, levels, metadata, timestamps

Clock Testing

const container = createTestContainer({ initialTime: 1000 });
const clock = await container.resolve(testClock);

assert.strictEqual(clock.now(), 1000);
clock.advanceBy(500);
assert.strictEqual(clock.now(), 1500);

HTTP Testing

const container = createTestContainer();
const client = await container.resolve(httpClientStub);

// Queue responses
client.queueResponse(new Response('{"status": "ok"}'));

// Make request
const response = await client.fetch('/api/status');
const data = await response.json();

// Verify requests
const requests = client.getSentRequests();
assert.strictEqual(requests[0].url, '/api/status');

Real-World Testing Patterns

Pattern 1: Testing with Real In-Memory Databases

Instead of mocking database operations, use real in-memory databases for more accurate testing:

import assert from 'node:assert/strict';
import { describe, test } from 'node:test';
import { createTestContainer, withBlobOverride } from '@speajus/diblob-testing';
import Database from 'better-sqlite3';
import { drizzle } from 'drizzle-orm/better-sqlite3';
import * as schema from './db/schema.js';
import { database } from './drizzle.js';
import { UserServiceImpl } from './user-service.js';

describe('UserService Tests', () => {
  // Helper to create a test database with schema
  const createTestDatabase = () => {
    const sqliteDb = new Database(':memory:');

    // Create the schema
    sqliteDb.exec(`
      CREATE TABLE users (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        name TEXT NOT NULL,
        email TEXT NOT NULL UNIQUE,
        created_at INTEGER NOT NULL
      )
    `);

    const db = drizzle(sqliteDb, { schema });
    return { sqliteDb, db };
  };

  test('should create a user successfully', async () => {
    const container = createTestContainer();
    const { sqliteDb, db } = createTestDatabase();

    try {
      await withBlobOverride(container, database, db, async () => {
        const service = new UserServiceImpl(database);

        const user = await service.createUser({
          name: 'John Doe',
          email: '[email protected]'
        });

        assert.strictEqual(user.name, 'John Doe');
        assert.strictEqual(user.email, '[email protected]');
      });
    } finally {
      sqliteDb.close();
    }
  });
});

Pattern 2: Integration Tests with Full Container Setup

Test complete workflows with all dependencies registered:

import assert from 'node:assert/strict';
import { describe, test } from 'node:test';
import { createContainer } from '@speajus/diblob';
import { registerGrpcBlobs } from '@speajus/diblob-connect';
import { setupEachTestContainer } from '@speajus/diblob-testing';
import { registerDrizzleBlobs, registerUserService } from './register.js';
import { userService } from './user-service.js';
import { sqlite } from './drizzle.js';

describe('gRPC Service Integration Tests', () => {
  const { getContainer } = setupEachTestContainer();

  // Helper to create database schema
  async function createSchema(container) {
    const db = await container.resolve(sqlite);
    db.exec(`
      CREATE TABLE IF NOT EXISTS users (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        name TEXT NOT NULL,
        email TEXT NOT NULL UNIQUE,
        created_at INTEGER NOT NULL
      )
    `);
  }

  test('should create and retrieve a user through service', async () => {
    const container = getContainer();
    registerDrizzleBlobs(container, ':memory:');
    await createSchema(container);
    registerGrpcBlobs(container, { host: '0.0.0.0', port: 50053 });
    registerUserService(container);

    const service = await container.resolve(userService);

    // Create a user
    const createResponse = await service.createUser({
      name: 'Integration Test User',
      email: '[email protected]'
    });

    assert.ok(createResponse.user);
    assert.strictEqual(createResponse.user.name, 'Integration Test User');

    // Retrieve the user
    const getResponse = await service.getUser({
      id: createResponse.user.id
    });

    assert.strictEqual(getResponse.user.id, createResponse.user.id);
    assert.strictEqual(getResponse.user.name, 'Integration Test User');
  });
});

Pattern 3: Container Lifecycle Testing

Test that your container setup, registration, and disposal work correctly:

import assert from 'node:assert/strict';
import { describe, test } from 'node:test';
import { createContainer } from '@speajus/diblob';
import { registerDrizzleBlobs, registerUserService } from './register.js';
import { database, sqlite } from './drizzle.js';
import { userService } from './user-service.js';

describe('Container Lifecycle Tests', () => {
  test('should register and resolve database blobs', async () => {
    const container = createContainer();
    registerDrizzleBlobs(container, ':memory:');

    // Verify database blobs are registered
    const db = await container.resolve(database);
    assert.ok(db);
    assert.ok(db.query);

    const sqliteDb = await container.resolve(sqlite);
    assert.ok(sqliteDb);
    assert.strictEqual(typeof sqliteDb.close, 'function');

    await container.dispose();
  });

  test('should properly dispose container and close database', async () => {
    const container = createContainer();
    registerDrizzleBlobs(container, ':memory:');

    const sqliteDb = await container.resolve(sqlite);
    assert.ok(sqliteDb.open, 'Database should be open');

    // Dispose container
    await container.dispose();

    // Verify database is closed
    assert.ok(!sqliteDb.open, 'Database should be closed after dispose');
  });
});

Pattern 4: Blob Override for Dependency Injection

Override specific dependencies without affecting the entire container:

import assert from 'node:assert/strict';
import { test } from 'node:test';
import { createTestContainer, withBlobOverride } from '@speajus/diblob-testing';
import { exampleWebConfig } from './diblob/blobs.js';
import { UserGateway } from './user-gateway.js';

test('should use test configuration', async () => {
  const container = createTestContainer();

  const testConfig = {
    apiBaseUrl: 'http://test-server:8080',
    visualizerEventsUrl: 'http://test-visualizer:3001/events'
  };

  await withBlobOverride(container, exampleWebConfig, testConfig, async () => {
    const gateway = await container.resolve(UserGateway);
    // Gateway will use test configuration
    const users = await gateway.fetchUsers();
    assert.ok(Array.isArray(users));
  });
});

Best Practices

  1. Use real in-memory databases instead of mocks for database testing - provides more accurate behavior and catches integration issues
  2. Use setupEachTestContainer() for most tests to ensure complete isolation between tests
  3. Use setupFileScopedTestContainer() when you need to share expensive setup across tests (use sparingly)
  4. Use withBlobOverride() to temporarily replace dependencies without affecting other tests
  5. Create helper functions for common setup like database schema creation
  6. Always clean up resources in finally blocks when using external resources like database connections
  7. Test container lifecycle to ensure proper registration and disposal of resources
  8. Configure deterministic seeds for reproducible test runs with testRandom and testClock

Integration with Existing Code

The package follows diblob conventions with separate blob definitions, implementations, and registration helpers:

  • Blob definitions in separate files (e.g., drizzle.ts, blobs.ts)
  • Implementations in implementation files (e.g., user-service.ts)
  • Registration functions that accept a container parameter (e.g., registerDrizzleBlobs(container))

This pattern integrates seamlessly with existing diblob applications and can be used alongside production containers.

Examples

See the following examples for complete implementations:

  • examples/example-grpc-server - Comprehensive testing of a gRPC server with Drizzle ORM
    • Unit tests with in-memory databases
    • Integration tests with full container setup
    • Container lifecycle tests
  • examples/example-web-svelte - Testing Svelte web applications with diblob

License

MIT