我正在尝试模拟一个存储库。我不想做真正的数据库调用。我(认为我)正在遵循关于NestJS和某些堆栈溢出项的文档。
但是,当我运行测试时,我会得到以下错误:
JwtStrategy › validate › throws an unauthorized exception as user cannot be found
Nest can't resolve dependencies of the UserEntityRepository (?). Please make sure that the argument DataSource at index [0] is available in the TypeOrmModule context.
Potential solutions:
- If DataSource is a provider, is it part of the current TypeOrmModule?
- If DataSource is exported from a separate @Module, is that module imported within TypeOrmModule?
@Module({
imports: [ /* the Module containing DataSource */ ]
})
现在,据我所知,UserEntityRepository似乎没有被正确地模仿。由于它是用户服务类中的第一个(索引)依赖项:
./user.service.ts
@Injectable()
export class UserService {
constructor(
@InjectRepository(UserEntity)
private userRepository: Repository<UserEntity>
) {}
async findOneBy({ username }): Promise<UserEntity> {
return await this.userRepository.findOneBy({ username })
}
}
./jwt.strategy.ts
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor(
private userService: UserService,
) {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: process.env.JWT_SECRET || config.get('jwt.secret'),
})
}
async validate(payload: JwtPayload) {
const { username } = payload;
const user = await this.userService.findOneBy({username});
if (!user) {
throw new UnauthorizedException();
}
return user;
}
}
./jwt.strategy.spect.ts
const mockUserRepositoryFactory = jest.fn(() => ({
findOneBy: jest.fn(entity => entity),
}));
describe('JwtStrategy', () => {
let jwtStrategy: JwtStrategy;
let userService;
beforeEach(async () => {
const module = await Test.createTestingModule({
imports: [UserModule],
providers: [
JwtStrategy,
UserService,
// shouldn't this correctly provide the datasource?
{
provide: getRepositoryToken(UserEntity),
useFactory: mockUserRepositoryFactory,
},
]
}).compile();
jwtStrategy = await module.get<JwtStrategy>(JwtStrategy);
userService = await module.get<UserService>(UserService);
});
describe('validate', () => {
it('validates and returns user based on JWT payload', async () => {
const user = new UserEntity();
user.username = 'TestUser';
userService.findOneBy.mockResolvedValue(user);
const result = await jwtStrategy.validate({ username: 'TestUser' });
expect(userService.findOneBy).toHaveBeenCalledWith({ username: 'TestUser' });
expect(result).toEqual(user);
});
it('throws an unauthorized exception as user cannot be found', async () => {
userService.findOneBy.mockResolvedValue(null);
expect(jwtStrategy.validate({ username: 'TestUser' })).rejects.toThrow(UnauthorizedException);
});
});
});
=====更新
在代码框中创建了一个最小的设置。
https://codesandbox.io/s/xenodochial-benz-kve4eq?file=/test/jwt.test.js
但是不知怎么的,测试选项卡没有显示在沙箱中。
发布于 2022-09-05 08:14:18
首先,您必须模拟DataSource (如果您愿意,可以创建一个单独的文件)
import { DataSource } from "typeorm";
// @ts-ignore
export const dataSourceMockFactory: () => MockType<DataSource> = jest.fn(() => ({
<mock_function>: jest.fn(),
}));
export type MockType<T> = {
[P in keyof T]?: jest.Mock<{}>;
};
然后创建一个测试文件
describe('---MSG---', () => {
...
let dataSourceMock: MockType<DataSource>
...
beforeAll(async () => {
const module = await Test.createTestingModule({
imports: [],
controllers: [<CONTROLLERS>],
providers: [ <PROVIDERS>
{ provide: DataSource, useFactory: dataSourceMockFactory }],
}).compile()
...
dataSourceMock = module.get(DataSource);
...
})
describe('---MSG---', () => {
it('---MSG---', async () => {
await <Call mock function>
expect(dataSourceMock.<DataSource mocked function>).toBeCalled();
});
})
发布于 2022-07-18 08:45:39
我注意到您正在服务中调用findOneBy
,但是模拟了findOne
存储库方法。
您必须模拟服务的findOne
方法或存储库的findOneBy
。在当前的方法中,您可以模拟存储库。此用例的解决方案如下所示:
const mockUserRepositoryFactory = jest.fn(() => ({
// Change here from findOne to findOneBy
findOneBy: jest.fn(entity => entity),
}));
describe('JwtStrategy', () => {
let jwtStrategy: JwtStrategy;
let userService;
beforeEach(async () => {
const module = await Test.createTestingModule({
imports: [UserModule],
providers: [
JwtStrategy,
UserService, {
provide: getRepositoryToken(UserEntity),
useFactory: mockUserRepositoryFactory,
},
]
}).compile();
jwtStrategy = await module.get<JwtStrategy>(JwtStrategy);
userService = await module.get<UserService>(UserService);
});
describe('validate', () => {
it('validates and returns user based on JWT payload', async () => {
const user = new UserEntity();
user.username = 'TestUser';
// change findOne to findOneBy here as well
userService.findOneBy.mockResolvedValue(user);
const result = await jwtStrategy.validate({ username: 'TestUser' });
expect(userService.findOneBy).toHaveBeenCalledWith({ username: 'TestUser' });
expect(result).toEqual(user);
});
it('throws an unauthorized exception as user cannot be found', async () => {
userService.findOneBy.mockResolvedValue(null);
expect(jwtStrategy.validate({ username: 'TestUser' })).rejects.toThrow(UnauthorizedException);
});
});
});
https://stackoverflow.com/questions/73019162
复制相似问题