mocking - Nestjs单元测试添加第二个服务模块手动模拟不起作用
问题描述
我使用 Nest 开发应用程序后端,当我编写单元测试时,我发现如果我只添加一个服务模块手动模拟,模拟工作正常。但是,如果我为第二个服务模块添加手动模拟,则测试出错并出现错误“...不是函数”,当只有一个服务模块模拟时,它工作得很好。测试框架是 Jest,有人知道为什么会这样吗?
下面是一个例子,在阅读器控制器单元测试中,原来只是在mocks文件夹中使用 readerService 手动模拟,所有测试用例都通过了。然后我需要添加一个 tokenService 依赖项,所以我也在mocks文件夹中添加了 tokenService 手动模拟,然后所有测试用例(之前都通过)没有通过,因为“this.readerService.*** is not a function”,看起来就像添加第二个手动模拟导致第一个手动模拟在某处失败。以下是单元测试代码的一部分:
import { ReaderController } from './reader.controller';
import { ReaderService } from './reader.service';
import { TokenService } from './token.service';
jest.mock('./reader.service').mock('./token.service');
describe('ReaderController', () => {
let readerController: ReaderController;
let readerService: ReaderService;
let tokenService: TokenService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
imports: [],
controllers: [ReaderController],
providers: [ReaderService, TokenService],
}).compile();
readerController = module.get<ReaderController>(ReaderController);
readerService = module.get<ReaderService>(ReaderService);
tokenService = module.get<TokenService>(TokenService);
jest.clearAllMocks();
});
describe('getProfile', () => {
describe('when getProfile is called', () => {
let reader: Reader;
beforeEach(async () => {
reader = await readerController.getProfile(readerStub()._id);
});
test('then it should call readerService', () => {
expect(readerService.getProfile).toHaveBeenCalledWith(readerStub()._id);
});
test('then it should return a reader object', () => {
expect(reader).toEqual(readerStub());
});
});
});
以下是 ReaderService 的手动模拟:
export const ReaderService = jest.fn().mockReturnValue({
register: jest.fn().mockResolvedValue(readerStub()),
findOne: jest.fn().mockResolvedValue(readerStub()),
getProfile: jest.fn().mockResolvedValue(readerStub()),
updateProfile: jest.fn().mockResolvedValue(readerStub()._id),
changePwd: jest.fn().mockResolvedValue(readerStub().username),
login: jest.fn().mockResolvedValue(accessTokenStub()),
tokenRefresh: jest.fn().mockReturnValue(accessTokenStub()),
logout: jest.fn().mockResolvedValue(readerStub()._id),
addFavourBook: jest.fn().mockResolvedValue(2),
getFavourBookList: jest.fn().mockResolvedValue(readerStub().favouriteBook),
delFavourBook: jest.fn().mockResolvedValue(2),
getReadBooks: jest.fn().mockResolvedValue([bookStub()]),
getReadHistory: jest.fn().mockResolvedValue(readerStub().readHistory),
});
以下是 TokenService 的手动模拟:
export const TokenService = jest.fn().mockReturnValue({
createToken: jest.fn().mockResolvedValue(tokenStub()),
verifyToken: jest.fn().mockResolvedValue(true),
delToken: jest.fn().mockResolvedValue(tokenStub().readerName),
resetPwd: jest.fn().mockResolvedValue(tokenStub().readerName),
verifyEmail: jest.fn().mockResolvedValue(tokenStub().readerName),
});
所有这些模拟文件都位于测试文件文件夹下的模拟文件中,所有这些设置都遵循 Jest 文件。谢谢你的帮助!
解决方案
我刚刚找到了解决方法,使用手动模拟的主要服务,然后直接在测试中添加第二个服务的模拟定义,就在测试功能(第一个描述)之前。然后在测试模块定义中为第二个服务定义模拟(第一个服务只使用提供的原始名称),然后两个模拟都可以正常工作。我认为 Nest 在模拟折叠中手动使用 2 个服务模拟可能有一些限制。
推荐阅读
- excel - 使用 INDEX MATCH MATCH 或 SUMIFS 聚合数据
- css - 为什么 Safari 的默认字体跟踪/字母间距与其他浏览器不同?
- oracle - 基于列值创建条件索引
- excel - 如何以编程方式获取单元格引用
- elasticsearch - 在聚合内部过滤 Elasticsearch 查询
- javascript - 你能在 Redis 中安全地存储 JavaScript 类实例吗?
- delphi - TMainMenu 中的单选项目不使用点,而是使用复选标记
- python - 如何在 matplotlib 中创建一个作用于旋转方向的自定义 blended_transform?
- javascript - new Date() 从打字稿类创建错误的日期
- firebase - 电子邮件地址格式错误 Firebase/React-Native