У меня есть класс Typescript, который использует InversifyJS и Inversify Inject Decorators для внедрения службы в частную собственность.С функциональной точки зрения это нормально, но у меня возникли проблемы с выяснением, как его тестировать.Я создал упрощенную версию моей проблемы ниже.
В модульном тесте Жасмин, как я могу поменять впрыснутый RealDataService
на FakeDataService
?Если свойство не было частным, я мог бы создать компонент и назначить поддельную службу, но мне интересно, возможно ли это с помощью контейнера IOC.
Я изначально следовал этому этому примеру в рецептах InversifyJSpage , но быстро понял, что созданный ими контейнер не используется ни в одном тестируемом классе.Кроме того, большинство примеров кода, которые я вижу в документах InversifyJS , не описывают, как выполнить его модульное тестирование.
Вот упрощенная версия проблемы:
myComponent.ts
import { lazyInject, Types } from "./ioc";
import { IDataService } from "./dataService";
export default class MyComponent {
@lazyInject(Types.IDataService)
private myDataService!: IDataService;
getSomething(): string {
return this.myDataService.get();
}
}
dataService.ts
import { injectable } from "inversify";
export interface IDataService {
get(): string;
}
@injectable()
export class RealDataService implements IDataService {
get(): string {
return "I am real!";
}
}
Конфигурация IOC
import "reflect-metadata";
import { Container, ContainerModule, interfaces, BindingScopeEnum } from "inversify";
import getDecorators from "inversify-inject-decorators";
import { IDataService, RealDataService } from "./dataService";
const Types = {
IDataService: Symbol.for("IDataService")
};
const iocContainerModule = new ContainerModule((bind: interfaces.Bind) => {
bind<IDataService>(Types.IDataService).to(RealDataService);
});
const iocContainer = new Container();
iocContainer.load(iocContainerModule);
const { lazyInject } = getDecorators(iocContainer);
export { lazyInject, Types };
Модульные тесты
import { Container } from "inversify";
import { Types } from "./ioc";
import MyComponent from "./myComponent";
import { IDataService } from "./dataService";
class FakeDataService implements IDataService {
get(): string {
return "I am fake!";
}
}
describe("My Component", () => {
let iocContainer!: Container;
let myComponent!: MyComponent;
beforeEach(() => {
iocContainer = new Container();
iocContainer.bind(Types.IDataService).to(FakeDataService);
// How do I make myComponent use this iocContainer?
// Is it even possible?
myComponent = new MyComponent();
});
it("should use the mocked service", () => {
const val = myComponent.getSomething();
expect(val).toBe("I am fake!");
});
});