【发布时间】:2019-10-10 23:24:24
【问题描述】:
尝试为我的 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 类会覆盖 DbService 的“findAll”方法来进行一些缓存操作。
我的测试脚本有这个:
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]);
});
});
});
});
现在,很明显 findAll 的 mockImplementation 模拟了 MyService 上的“findAll”,所以测试失败了,因为 spy_cacheset 从未被调用过。
我想做的是仅模拟 DbService 中的基本方法“findAll”,以便我维护 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,而不模拟整个“共享”项目?
【问题讨论】: