UNPKG

krispy

Version:

Basic synchronous dependency injector

159 lines 7.11 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const chai_1 = require("chai"); const Injector_1 = __importDefault(require("../lib/Injector")); const UnresolvableDependencyException_1 = __importDefault(require("../lib/exception/UnresolvableDependencyException")); const CannotRegisterDependencyException_1 = __importDefault(require("../lib/exception/CannotRegisterDependencyException")); const UnexpectedStateException_1 = __importDefault(require("../lib/exception/UnexpectedStateException")); const InjectorUtil_1 = __importDefault(require("../lib/util/InjectorUtil")); function getInjectorData(injector) { return injector['_items']; } describe('InjectorUtil', function () { describe('isInheritedFrom', function () { it('returns false when the classes are not descended from one another', function () { class ClassA { } class ClassB { } chai_1.expect(InjectorUtil_1.default.isInheritedFrom(ClassA, ClassB)).to.be.false; }); it('returns true when the inherited class is a direct descendant', function () { class Base { } class Inherited extends Base { } chai_1.expect(InjectorUtil_1.default.isInheritedFrom(Base, Inherited)).to.be.true; }); it('returns true when the inherited class is a second-level descendant', function () { class BaseA { } class BaseB extends BaseA { } class Inherited extends BaseB { } chai_1.expect(InjectorUtil_1.default.isInheritedFrom(BaseB, Inherited)).to.be.true; chai_1.expect(InjectorUtil_1.default.isInheritedFrom(BaseA, Inherited)).to.be.true; }); it('returns false when the prototype of the inherited is null', function () { class Base { } class Inherited extends Base { } Reflect.setPrototypeOf(Inherited, null); chai_1.expect(InjectorUtil_1.default.isInheritedFrom(Base, Inherited)).to.be.false; }); }); }); describe('Injector', function () { let injector; beforeEach(function () { injector = new Injector_1.default(); }); describe('global', function () { it('does not instantiate global upon module loading', function () { chai_1.expect(Injector_1.default['_globalInjector'] == null, 'global injector was instantiated already').to.be.true; }); it('returns an instance of the Injector upon first call', function () { chai_1.expect(Injector_1.default.global).to.be.an.instanceOf(Injector_1.default); }); it('always returns the same global instance', function () { chai_1.expect(Injector_1.default.global).to.equal(Injector_1.default.global); }); }); describe('add', function () { it('adds to data when registering dependency', function () { class Base { } class Sub extends Base { } injector.addSingleton(Base, Sub); const injectorData = getInjectorData(injector); chai_1.expect(injectorData.has(Base), 'Injector data did not add dependency to data').to.be.true; }); it('throws CannotRegisterDependencyException when subclass does not inherit from base class', function () { class Base { } class Sub { } chai_1.expect(() => injector.addSingleton(Base, Sub)).to.throw(CannotRegisterDependencyException_1.default); }); }); describe('resolve', function () { it('Successfully resolves a registered instance', function () { class Base { } class Sub extends Base { } injector.addSingleton(Base, Sub); const sub = injector.resolve(Base); chai_1.expect(sub).to.be.an.instanceOf(Base); chai_1.expect(sub).to.be.an.instanceOf(Sub); }); it('Only constructs singletons once', function () { class Base { } let constructCount = 0; class Singleton extends Base { constructor() { super(); constructCount++; } } injector.addSingleton(Base, Singleton); for (let i = 0; i < 5; ++i) { const instance = injector.resolve(Base); chai_1.expect(instance).to.be.an.instanceOf(Base); chai_1.expect(instance).to.be.an.instanceOf(Singleton); } chai_1.expect(constructCount).to.equal(1); }); it('Constructs transient every single time', function () { class Base { } let constructCount = 0; class Transient extends Base { constructor() { super(); constructCount++; } } injector.addTransient(Base, Transient); const resolveCount = 5; for (let i = 0; i < resolveCount; ++i) { const instance = injector.resolve(Base); chai_1.expect(instance).to.be.an.instanceOf(Base); chai_1.expect(instance).to.be.an.instanceOf(Transient); } chai_1.expect(constructCount).to.equal(resolveCount); }); it('throws UnresolvableDependencyException when dependency is not registered', function () { class Base { } chai_1.expect(() => injector.resolve(Base)).to.throw(UnresolvableDependencyException_1.default); }); it('throws UnresolvableDependencyInjection when dependency data is null', function () { class Base { } const injectorData = getInjectorData(injector); // @ts-ignore - We know null is not a valid type to be setting, but this is the test injectorData.set(Base, null); chai_1.expect(() => injector.resolve(Base)).to.throw(UnresolvableDependencyException_1.default); }); it('throws UnexpectedStateException when the injector type is unknown', function () { class Base { } class Sub extends Base { } injector.addSingleton(Base, Sub); const injectorData = getInjectorData(injector); // @ts-ignore - Don't care if it can be null, other tests should have checked for that injectorData.get(Base).type = -1; chai_1.expect(() => injector.resolve(Base)).to.throw(UnexpectedStateException_1.default); }); }); }); //# sourceMappingURL=injector.test.js.map