Как правильно замокать метод updateOne mongoose в Nest.js используя Jest
Я хочу замокать метод updateOne в приложении Nest.js используя библиотеку для тестов Jest.
У меня есть метод сервиса
public async update(
newDto: UpdateUserFieldsDTO,
userName: string,
): Promise<UserDocument> {
const updatedUser = await this.findUserByUserName(userName);
await this.userModel.updateOne({ userName }, { $set: { ...newDto } });
return updatedUser;
}
В нем я обращаюсь к другому методу класса чтоб найти юзера, вот его код
public async findUserByUserName(
userName: string,
): Promise<UserDocument | null> {
return await this.userModel.findOne({ userName, deletedAt: null });
}
Я написал тесты для методов и вот что у меня вышло
import { Test, TestingModule } from "@nestjs/testing";
import { UserService } from "./user.service";
import { User, UserRole } from "./models/user.model";
import { getModelToken } from "@nestjs/mongoose";
import { JwtService } from "@nestjs/jwt";
import { AuthService } from "../auth/auth.service";
import { ConfigService } from "@nestjs/config";
import { CreateUserDTO } from "./dto/createUser.dto";
import { UpdateUserFieldsDTO } from "./dto/updateUser.dto";
const mockUser: CreateUserDTO = {
email: "[email protected]",
firstName: "str",
lastName: "str",
password: "str",
userName: "userName",
};
const mockUserObject = {
_id: "12345",
email: mockUser.email,
firstName: mockUser.firstName,
lastName: mockUser.lastName,
password: mockUser.password,
userName: mockUser.userName,
role: UserRole.USER,
salt: "salt",
rating: 0,
lastVoteAt: null,
createdAt: new Date(),
updatedAt: new Date(),
deletedAt: null,
};
class MockedMongoModel {
constructor(private user: CreateUserDTO) {}
static readonly findOne = jest.fn(
async (query: { userName?: string; _id?: string; email?: string }) => {
if (query._id) {
return query._id === mockUserObject._id ? mockUserObject : null;
} else if (query.email)
return query.email === mockUserObject.email
? mockUserObject
: null;
return query.userName === mockUser.userName ? mockUserObject : null;
},
);
static readonly updateOne = jest.fn(
async (userName: string, newUserData: UpdateUserFieldsDTO) => {
const user = await this.findOne({ userName });
if (newUserData.userName) {
user.userName = newUserData.userName;
return user;
}
},
);
}
const MockedAuthModel = {
generateRandomStr: jest.fn().mockReturnValue("randomStr"),
hashPassword: jest.fn().mockReturnValue("str"),
};
describe("UserService", () => {
let service: UserService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
UserService,
{
provide: getModelToken(User.name),
useValue: MockedMongoModel,
},
{
provide: AuthService,
useValue: MockedAuthModel,
},
JwtService,
ConfigService,
],
}).compile();
service = module.get<UserService>(UserService);
jest.clearAllMocks();
});
afterEach(() => {
jest.clearAllMocks();
});
it("should be defined", () => {
expect(service).toBeDefined();
});
it.only("should update user's userName", async () => {
const updatedUser = {
...mockUserObject,
userName: "user",
};
const expectedOutput = await service.update(
{ userName: "user" },
mockUser.userName,
);
expect(MockedMongoModel.updateOne).toHaveBeenCalledTimes(1);
expect(expectedOutput).toEqual(updatedUser);
});
});
И тут я в замоканном методе обращаюсь к методу класса await this.findOne({ userName })
чтоб получить пользователя. После запуска тестов я вижу картинку такую
В ошибке я вижу что я ожидаю измененного пользователя с "userName": "user"
но получаю "userName": "userName"
, что говорит о том что код
if (newUserData.userName) {
user.userName = newUserData.userName;
return user;
}
не выполняется.
Кто может подсказать что я сделал не так? И как исправить мой код чтоб я получил все таки измененного пользователя и прошел данный тест?