如何在Jest中模拟MongoDB query .exec()?

ggazkfy8  于 2023-08-01  发布在  Jest
关注(0)|答案(2)|浏览(132)

我想用Jest in a Typescript Express env来模拟这个异步函数。

// src/helpers/user.ts
import { UserModel } from "../models";

export const getUserByUsername = async (username: string) => {
  return UserModel.findOne({ username }).exec()
}

个字符
以下是我失败的测试:

// src/helpers/user.test.ts
describe("getUserByUsername():", () => {
  test('should return a user if username matches', async () => {
    const mockUser: User = await userFactory.build("user");

    const spy = jest.spyOn(UserModel, "findOne");
    spy.mockImplementationOnce(() => Promise.resolve(mockUser))

    const userByUsernameResult = usersHelper.getUserByUsername(mockUser.username);

    await expect(userByUsernameResult).resolves.toEqual(expect.objectContaining({ username: mockUser.username })); 
  });
});


我得到的错误消息:
expect(received).resolves.toEqual()接收到的promise rejected而不是resolved Rejected的值:[类型错误:models_1.UserModel.findOne(...).exec不是函数]
你能帮帮我吗?

UPDATE:我在其他一些测试中使用了在这种情况下也有效的MongoDB Memory Server方法(见下文)。然而,我真的很想知道如何通过模拟.exec()(见上文)来实现这一点。

// src/helpers/user.test.ts
beforeAll(async () => {
  await mongoose.connect(process.env.MONGO_URL as string, { useNewUrlParser: true, useUnifiedTopology: true } as ConnectOptions, (err) => {
    if(err) {
      console.error(err);
      process.exit(1);
    }
  })
});

afterAll(async () => {
  await mongoose.connection.close();
});

describe("getUserByUsername():", () => {
  test('should return a user if username matches', async () => {
    const mockUser: User = await userFactory.build("user", {}, { setId: false });

    const validUser = new UserModel(mockUser);
    await validUser.save();

    const userByUsernameResult = usersHelper.getUserByUsername(mockUser.username);

    await expect(userByUsernameResult).resolves.toEqual(expect.objectContaining({ username: mockUser.username }));
  });

6yjfywim

6yjfywim1#

我认为这种做法应该行得通。

const findOneMock = jest.spyOn(UserModel, 'findOne');
    findOneMock.mockResolvedValueOnce({ exec: jest.fn().mockResolvedValue(mockUser) } as any)

字符串
在类型错误情况下,对模拟对象方法进行显式类型Assert。

findOneMock.mockResolvedValueOnce({
      exec: jest.fn().mockResolvedValue(mockUser) as unknown as () => Promise<User>,
    } as any);

41zrol4v

41zrol4v2#

您的情况与this问题非常相似。
与上面给出的答案类似,你可以这样做:

UserModel.findOne = jest.fn().mockImplementationOnce(() => ({ exec: jest.fn().mockResolvedValueOnce(() => {/* Your value here.*/})}));

字符串
详细说明并为答案增加一些价值:exec()是与UserModel.findOne()上的调用链接的方法。因此,你必须在两个层面上嘲笑:一个定义了UserModel.findOne()的模拟实现,另一个将exec()模拟为UserModel.findOne的链调用,并指定了它返回的值。
如果你想在链中继续模拟,你必须为exec()定义一个模拟实现,同时使用mockImplementationOnce,为链提供所需的方法,等等。

相关问题