Попытка написать тестовые сценарии для моего приложения nestjs.
У меня есть контроллер / сервисная структура, которая выглядит следующим образом:
Контроллер:
export class MyController {
constructor(
protected _svc: MyService
) {}
@Get()
async getAll(): Promise<Array<Person>> {
return await this._svc.findAll();
}
}
Услуги:
@Injectable()
export class MyService extends DbService < Person > {
constructor(
private _cache: CacheService
) {
super(...);
}
async findAll() {
return super.findAll().then(res => {
res.map(s => {
this._cache.setValue(`key${s.ref}`, s);
});
return res;
});
}
Базовый класс:
@Injectable()
export abstract class DbService<T> {
constructor() {}
async findAll(): Promise<Array<T>> {
...
}
}
Мой контроллер является точкой входа при вызове конечной точки в API. Это вызывает сервис, который расширяет DbService, который связывается с моей базой данных. Есть много сервисов, которые расширяют этот DbService. В этом случае класс MyService переопределяет метод «findAll» DbService, чтобы выполнить некоторые манипуляции с кэшем.
Мой тестовый скрипт имеет следующее:
let myController: MyController;
let myService: MyService;
describe("MyController", async () => {
let spy_findall, spy_cacheset;
beforeAll(() => {
this._cacheService = {
// getValue, setValue, delete methods
};
myService = new MyService(this._cacheService);
myController = new MyController(myService);
spy_findall = jest.spyOn(myService, "findAll").mockImplementation(async () => {
return [testPerson];
});
spy_cacheset = jest.spyOn(this._cacheService, "setValue");
});
beforeEach(async () => {
jest.clearAllMocks();
});
describe("getAll", () => {
it("should return an array of one person", async () => {
await myController.getAll().then(r => {
expect(r).toHaveLength(1);
expect(spy_findall).toBeCalledTimes(1);
expect(spy_cacheset).toBeCalledTimes(1);
expect(r).toEqual([testPerson]);
});
});
});
});
Теперь, очевидно, mockImplementation findAll высмеивает «findAll» на MyService, поэтому тест не пройден, потому что spy_cacheset никогда не вызывается.
Я хотел бы только макет только базовый метод "findAll" из DbService, чтобы я поддерживал дополнительную функциональность, существующую в MyService.
Есть ли способ сделать это, не переименовывая методы в MyService, чего я бы предпочел избегать?
Отредактировано, чтобы добавить:
Спасибо @Jonatan lenco за такой исчерпывающий ответ, который я принял и реализовал.
У меня есть еще один вопрос. CacheService, DbService и множество других вещей (некоторые из которых я хочу издеваться, другие - нет) находятся во внешнем библиотечном проекте, «разделяемом».
cache.service.ts
export class CacheService {...}
index.ts
export * from "./shared/cache.service"
export * from "./shared/db.service"
export * from "./shared/other.stuff"
....
Затем он компилируется и включается как пакет в node_modules.
В проекте, в котором я пишу тесты:
import { CacheService, DocumentService, OtherStuff } from "shared";
Могу ли я по-прежнему использовать jest.mock () только для CacheService, без насмешек над всем "общим" проектом?