From 34016562193edcb38a515be67d6fbd40397f0589 Mon Sep 17 00:00:00 2001 From: "Max P." Date: Wed, 2 Apr 2025 21:47:17 +0200 Subject: [PATCH] test(inject): add test suite to verify behavior of new `inject()` function --- src/__tests__/Functions.spec.ts | 108 ++++++++++++++++++++++++++++++++ src/__tests__/Functions.test.ts | 1 + 2 files changed, 109 insertions(+) diff --git a/src/__tests__/Functions.spec.ts b/src/__tests__/Functions.spec.ts index ee2b198..4506f67 100644 --- a/src/__tests__/Functions.spec.ts +++ b/src/__tests__/Functions.spec.ts @@ -74,3 +74,111 @@ export function test_ResolveFunction( }); }); } + +/** + * Test the inject function. + * @param Container The DI container implementation to test against. + * @param inject The inject function to test. + */ +export function test_injectFunction( + Container: ITSinjex_, + // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type + inject: Function, +): void { + describe('inject Function Tests', () => { + let container: ITSinjex; + + beforeEach(() => { + // Reset singleton + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (Container as any)['_instance'] = undefined; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (Container as any)['_dependencies'] = undefined; + container = Container.getInstance(); + }); + + it('should resolve and return the dependency as is', () => { + container.register('SimpleDep', { value: 'test' }); + + const resolved = inject('SimpleDep'); + expect(resolved.value).toBe('test'); + }); + + it('should resolve and run the initializer function', () => { + container.register('DepWithInit', { value: 'before' }); + + const resolved = inject('DepWithInit', (dep: any) => { + dep.value = 'after'; + + return dep; + }); + + expect(resolved.value).toBe('after'); + }); + + it('should resolve and instantiate the dependency if init is true and constructor exists', () => { + class WithConstructor { + value = 'constructed'; + } + + container.register('Constructable', WithConstructor); + + const resolved = inject('Constructable', true); + expect(resolved.value).toBe('constructed'); + }); + + it('should return undefined if dependency is not found and not necessary', () => { + const resolved = inject('NonExistentDep', undefined, false); + expect(resolved).toBeUndefined(); + }); + + it('should throw DependencyResolutionError if dependency is not found and necessary', () => { + expect(() => inject('MissingDep')).toThrow( + DependencyResolutionError, + ); + }); + + it('should throw InitializationError if init function throws', () => { + container.register('InitThrows', {}); + + expect(() => + inject('InitThrows', () => { + throw new Error('fail'); + }), + ).toThrow(InitializationError); + }); + + it('should throw NoInstantiationMethodError if init = true and no constructor exists', () => { + container.register('NonConstructable', {}); + + expect(() => inject('NonConstructable', true)).toThrow( + NoInstantiationMethodError, + ); + }); + + it('should not throw if no constructor and necessary = false', () => { + container.register('SafeSkip', {}); + expect(() => inject('SafeSkip', true, false)).not.toThrow(); + }); + + it('should return undefined if initializer fails and not necessary', () => { + container.register('InitErrorOptional', {}); + + const result = inject( + 'InitErrorOptional', + () => { + throw new Error('ignored'); + }, + false, + ); + + expect(result).toBeUndefined(); + }); + + it('should return undefined if dependency is null and not necessary', () => { + container.register('NullDep', null); + const result = inject('NullDep', true, false); + expect(result).toBeUndefined(); + }); + }); +} diff --git a/src/__tests__/Functions.test.ts b/src/__tests__/Functions.test.ts index 110a128..cbf7e6c 100644 --- a/src/__tests__/Functions.test.ts +++ b/src/__tests__/Functions.test.ts @@ -10,3 +10,4 @@ import { resolve } from '../functions/resolve.js'; test_RegisterFunction(TSinjex, register); test_ResolveFunction(TSinjex, resolve); +test_injectFunction(TSinjex, inject);