【发布时间】:2020-07-15 02:58:36
【问题描述】:
我正在编写一个模拟在数据库中创建新用户的单元测试。在user.service.add 方法中,我调用findOne 来检查用户是否存在于数据库中。在开发中,这可以正常工作,但在测试中 - findOne 在不应该返回数据时返回数据。
至少我认为不应该。为什么要返回数据?
我的测试
const testUserUsername1 = faker.internet.userName();
const testUserEmail1 = faker.internet.email();
const testUserPassword1 = faker.internet.password();
const testUserName1 = `${faker.name.firstName()} ${faker.name.lastName()}`;
const testUserName2 = `${faker.name.firstName()} ${faker.name.lastName()}`;
// user test object
const testUser = new User(
testUserName1,
testUserEmail1,
testUserPassword1,
testUserUsername1,
);
describe('UserService', () => {
let userService: UserService;
let postService: PostService;
let likeService: LikeService;
let userRepository: Repository<User>;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
UserService,
{
provide: getRepositoryToken(User),
useClass: Repository,
},
{
provide: getRepositoryToken(User),
// mocks of all the methods from the User Service
useValue: {
save: jest.fn(),
create: jest.fn().mockReturnValue(testUser),
find: jest.fn().mockResolvedValue(testUsers),
findOne: jest.fn().mockResolvedValue(testUser),
update: jest.fn().mockResolvedValue(testUser),
delete: jest.fn().mockResolvedValue(true),
},
},
PostService,
{
provide: PostService,
useClass: Repository,
},
LikeService,
{
provide: LikeService,
useClass: Repository,
},
],
}).compile();
userRepository = module.get<Repository<User>>(getRepositoryToken(User));
userService = module.get<UserService>(UserService);
postService = module.get<PostService>(PostService);
likeService = module.get<LikeService>(LikeService);
});
it('should be able to create a user', async () => {
const tempUser = {
name: testUserName1,
email: testUserEmail1,
username: testUserUsername1,
password: testUserPassword1,
}
userRepository.findOne = jest.fn(() => tempUser.username);
await userService.add(tempUser)
expect(tempUser).toEqual(testUser);
});
afterEach(() => {
jest.resetAllMocks();
});
});
user.service.add
async add(userDto: Partial<UserCreateDTO>): Promise<UserDTO> {
// get data from args
const { name, password, username, email } = userDto;
// check if the user exists in the db
const userInDb = await this.userRepository.findOne({
where: { username },
});
console.log('username: ', username)
console.log('userInDb: ', userInDb)
if (userInDb) {
throw new HttpException('User already exists', HttpStatus.BAD_REQUEST);
}
// create new user
const user: User = await this.userRepository.create({
name,
password,
username,
email,
});
// save changes to database
await this.userRepository.save(user);
// return user object
return toUserDto(user);
}
user.service.add 中的console.log 输出
console.log src/user/user.service.ts:49
username: Mayra_Rolfson53
console.log src/user/user.service.ts:50
userInDb: User {
name: 'Albert Kuvalis',
email: 'Martin_Jacobson@gmail.com',
username: 'SQT_L6iGKzPVFPI',
password: 'Mayra_Rolfson53'
}
抛出错误
User already exists
50 | console.log('userInDb', userInDb)
51 | if (userInDb) {
> 52 | throw new HttpException('User already exists', HttpStatus.BAD_REQUEST);
| ^
53 | }
【问题讨论】:
-
你没有专门为模拟用户存储库定义这种行为吗? ``` findOne: jest.fn().mockResolvedValue(testUser), ```
-
我想我不是吗?哈哈。如果我不这样做,那么我会得到
findOne is not a function.. 如果我想在此之后的另一个测试中向 findOne 发送文本但仅在 this 的情况下我希望 findOne 什么都不返回怎么办? -
好的,所以测试的行为完全符合预期 - findOne() 每次调用时都会返回预定义的用户对象。您可能需要更改模拟行为以适应此特定测试的需要。如果这个 .fndOne() 在测试中只被调用一次,并且你需要它返回 null,那么就这样做!
findOne: jest.fn().mockResolvedVaue(null) -
啊,也可以!相反,我在下面用另一个解决方案写了一个答案,并在其中标记了 u。您也可以将此答案作为解决方案发布!
标签: unit-testing jestjs nestjs