我的目标是为nestjs项目中的自定义存储库文件中的函数添加一些单元测试。
服务:
@Injectable()
export class TacoService {
constructor(
public readonly tacoRepository: TacoRepository,
private readonly userRepository: UserRepository,
public readonly bcdaRepository: BurritoRepository,
@Inject(forwardRef(() => MakerService))
private readonly makerService: MakerService,
...
) {}
...
}
字符串
仓库:
@Injectable()
export class TacoRepository {
constructor(
@Inject(Topping.name) private readonly toppingRepository: typeof Topping,
@Inject(Sauce.name) private readonly sauceRepository: typeof Sauce,
...
) {}
public getTacoString(offset: number | undefined, limit: number | undefined) {
return !isUndefined(offset) && !isUndefined(limit) ? `${limit} ${offset}` : '';
}
...
}
型
测试:
describe('TacoRepository test suite', () => {
let tacoService: TacoService;
beforeAll(async () => {
const module = await Test.createTestingModule({
providers: [TacoService],
exports: [TacoService],
})
.useMocker(token => {
if (typeof token === 'function') {
const mockMetadata = moduleMocker.getMetadata(token) as MockFunctionMetadata<any, any>;
const Mock = moduleMocker.generateFromMetadata(mockMetadata);
return new Mock();
}
})
.compile();
tacoService = module.get<TacoService>(TacoService);
});
describe('Get taco string tests', () => {
let actual;
it('should return an empty taco string when the limit and/or offset are undefined', () => {
actual = tacoService.tacoRepository.getTacoString(undefined, undefined);
expect(actual).toEqual('');
actual = tacoService.tacoRepository.getTacoString(undefined, 10);
expect(actual).toEqual('');
actual = tacoService.tacoRepository.getTacoString(0, undefined);
expect(actual).toEqual('');
});
});
});
型
当我执行测试时,我总是得到一个“undefined”的实际值,这是因为TacoRepository被mock了。但是我不知道如何不mock这个仓库,然后mock TacoRepository的依赖项。
我尝试过使用TacoRepository而不是TacoService来创建测试模块,但这会导致错误,抱怨“Nest无法解决RootTestModule上下文中的依赖关系”。任何帮助或建议都将非常感谢。
1条答案
按热度按时间huwehgph1#
在其核心,
Test.createTestingModule
使用 * 标准 * 依赖注入功能创建了一个 * 标准 * NestJS模块。(Test.createTestingModule({ providers: [TacoService] })
),测试模块必须能够解析该提供程序的 * 所有依赖项(在您的示例中,这将是TacoService的所有依赖项-即TacoRepository,UserRepository,BurritoRepository和MakerService),以及依赖关系的依赖关系等等-整个依赖关系树。如果它不能做到这一点,它会抱怨(因为它确实-“不能解决依赖关系...”)。您使用
useMocker
函数的方式确保了 * 每个具有函数类型标记 *(本质上是类)的提供程序都被模拟(我相信不包括TacoService本身)。现在,TacoRepository也有依赖项(toppingRepo,sauceRepo等),但这些依赖项的注入令牌(我假设)是 * 字符串而不是函数。如果你模拟整个TacoRepository(这是你的代码中的情况),你就不需要再模拟它的依赖项了,所以代码运行得很好。
但是,如果您将TacoRepository添加到providers数组中,它的依赖项不会被模拟(因为它们的注入令牌是字符串,而您的
useMocker
只模拟函数令牌),NestJS无法解析它们并在运行测试时抛出错误。注射代币是什么?这需要你自己去研究。但是我会说,当你写
@Inject(Topping.name)
时,Topping.name
充当了一个注入令牌,它可能是一个字符串,对吗?所以你需要为这个令牌定义一些提供者,这样NestJS就知道在那里注入什么。这是解决问题的一种方法:
字符串
或者你可以用
=== "string"
条件来补充useMocker
中的=== "function"
条件:型
然而,如果你真的想单独测试TacoRepository(模拟它的所有依赖项),你最好不要完全使用Test模块。这是你在NestJS的文档中找到的第一个测试示例。
型
如果您希望模拟除了TacoRepository之外的所有内容,您可以尝试修改
useMocker
的使用以忽略该特定令牌。型