183 lines
5.3 KiB
TypeScript
183 lines
5.3 KiB
TypeScript
/**
|
|
* Test DI library functionality
|
|
*/
|
|
import { describe, expect, test } from 'bun:test';
|
|
import {
|
|
ConnectionFactory,
|
|
OperationContext,
|
|
PoolSizeCalculator,
|
|
ServiceContainer,
|
|
} from '../src/index';
|
|
|
|
describe('DI Library', () => {
|
|
test('ServiceContainer - sync resolution', () => {
|
|
const container = new ServiceContainer('test');
|
|
|
|
container.register({
|
|
name: 'testService',
|
|
factory: () => ({ value: 'test' }),
|
|
singleton: true,
|
|
});
|
|
|
|
const service = container.resolve<{ value: string }>('testService');
|
|
expect(service.value).toBe('test');
|
|
});
|
|
|
|
test('ServiceContainer - async resolution', async () => {
|
|
const container = new ServiceContainer('test');
|
|
|
|
container.register({
|
|
name: 'asyncService',
|
|
factory: async () => ({ value: 'async-test' }),
|
|
singleton: true,
|
|
});
|
|
|
|
const service = await container.resolveAsync<{ value: string }>('asyncService');
|
|
expect(service.value).toBe('async-test');
|
|
});
|
|
|
|
test('ServiceContainer - scoped container', () => {
|
|
const container = new ServiceContainer('test');
|
|
|
|
container.register({
|
|
name: 'testService',
|
|
factory: () => ({ value: 'test' }),
|
|
singleton: true,
|
|
});
|
|
|
|
const scopedContainer = container.createScope();
|
|
const service = scopedContainer.resolve<{ value: string }>('testService');
|
|
expect(service.value).toBe('test');
|
|
});
|
|
|
|
test('ServiceContainer - error on unregistered service', () => {
|
|
const container = new ServiceContainer('test');
|
|
|
|
expect(() => {
|
|
container.resolve('nonexistent');
|
|
}).toThrow('Service nonexistent not registered');
|
|
});
|
|
|
|
test('ServiceContainer - async service throws error on sync resolve', () => {
|
|
const container = new ServiceContainer('test');
|
|
|
|
container.register({
|
|
name: 'asyncService',
|
|
factory: async () => ({ value: 'async' }),
|
|
singleton: true,
|
|
});
|
|
|
|
expect(() => {
|
|
container.resolve('asyncService');
|
|
}).toThrow('Service asyncService is async. Use resolveAsync() instead.');
|
|
});
|
|
|
|
test('ServiceContainer - disposal', async () => {
|
|
const container = new ServiceContainer('test');
|
|
let disposed = false;
|
|
|
|
container.register({
|
|
name: 'disposableService',
|
|
factory: () => ({ value: 'test' }),
|
|
singleton: true,
|
|
dispose: async () => {
|
|
disposed = true;
|
|
},
|
|
});
|
|
|
|
// Create instance
|
|
container.resolve('disposableService');
|
|
|
|
// Dispose container
|
|
await container.dispose();
|
|
expect(disposed).toBe(true);
|
|
});
|
|
|
|
test('OperationContext - enhanced functionality', () => {
|
|
const container = new ServiceContainer('test');
|
|
const context = OperationContext.create('test-handler', 'test-operation', {
|
|
container,
|
|
metadata: { userId: '123' },
|
|
});
|
|
|
|
expect(context).toBeDefined();
|
|
expect(context.logger).toBeDefined();
|
|
expect(context.traceId).toBeDefined();
|
|
expect(context.metadata.userId).toBe('123');
|
|
expect(context.getExecutionTime()).toBeGreaterThanOrEqual(0);
|
|
});
|
|
|
|
test('OperationContext - service resolution', () => {
|
|
const container = new ServiceContainer('test');
|
|
|
|
container.register({
|
|
name: 'testService',
|
|
factory: () => ({ value: 'resolved' }),
|
|
singleton: true,
|
|
});
|
|
|
|
const context = OperationContext.create('test-handler', 'test-operation', {
|
|
container,
|
|
});
|
|
|
|
const service = context.resolve<{ value: string }>('testService');
|
|
expect(service.value).toBe('resolved');
|
|
});
|
|
|
|
test('ConnectionFactory - creation', () => {
|
|
const factory = new ConnectionFactory({
|
|
service: 'test',
|
|
environment: 'development',
|
|
});
|
|
|
|
expect(factory).toBeDefined();
|
|
expect(factory.listPools()).toEqual([]);
|
|
});
|
|
|
|
test('OperationContext - creation', () => {
|
|
const container = new ServiceContainer('test');
|
|
const context = OperationContext.create('test-handler', 'test-operation', {
|
|
container,
|
|
});
|
|
|
|
expect(context).toBeDefined();
|
|
expect(context.logger).toBeDefined();
|
|
});
|
|
|
|
test('OperationContext - child context', () => {
|
|
const context = OperationContext.create('test-handler', 'test-operation');
|
|
const child = context.createChild('child-operation');
|
|
|
|
expect(child).toBeDefined();
|
|
expect(child.logger).toBeDefined();
|
|
});
|
|
|
|
test('PoolSizeCalculator - service defaults', () => {
|
|
const poolSize = PoolSizeCalculator.calculate('data-ingestion');
|
|
expect(poolSize).toEqual({ min: 5, max: 50, idle: 10 });
|
|
});
|
|
|
|
test('PoolSizeCalculator - handler defaults', () => {
|
|
const poolSize = PoolSizeCalculator.calculate('unknown-service', 'batch-import');
|
|
expect(poolSize).toEqual({ min: 10, max: 100, idle: 20 });
|
|
});
|
|
|
|
test('PoolSizeCalculator - fallback defaults', () => {
|
|
const poolSize = PoolSizeCalculator.calculate('unknown-service', 'unknown-handler');
|
|
expect(poolSize).toEqual({ min: 2, max: 10, idle: 3 });
|
|
});
|
|
|
|
test('PoolSizeCalculator - custom config', () => {
|
|
const poolSize = PoolSizeCalculator.calculate('test-service', undefined, {
|
|
minConnections: 5,
|
|
maxConnections: 15,
|
|
});
|
|
expect(poolSize).toEqual({ min: 5, max: 15, idle: 5 });
|
|
});
|
|
|
|
test('PoolSizeCalculator - optimal size calculation', () => {
|
|
const optimalSize = PoolSizeCalculator.getOptimalPoolSize(10, 100, 50);
|
|
expect(optimalSize).toBeGreaterThan(0);
|
|
expect(typeof optimalSize).toBe('number');
|
|
});
|
|
});
|