如何在 Express router Jest 测试中模拟方法?

Kar*_*ren 3 javascript unit-testing node.js express jestjs

我正在尝试使用 Jest + Supertest 测试 Node.js 应用程序中的路由器,但我的路由器正在调用服务,该服务正在调用端点:

router.post('/login', async (req, res, next) => {
  try {
    const { username, password } = req.body;

    // I WANT TO MOCK userService.getUserInfo FUNCTION, BECAUSE IT IS MAKING A POST CALL
    const identity = await userService.getUserInfo(username, password);

    if (!identity.authenticated) {
      return res.json({});
    }

    const requiredTenantId = process.env.TENANT_ID;
    const tenant = identity.tenants.find(it => it.id === requiredTenantId);

    if (requiredTenantId && !tenant) {
      return res.json({});
    }

    const userResponse = {
      ...identity,
      token: jwt.sign(identity, envVars.getVar(envVars.variables.AUTH_TOKEN_SECRET), {
        expiresIn: '2h',
      }),
    };

    return res.json(userResponse);
  } catch (err) {
    return next(err);
  }
});
Run Code Online (Sandbox Code Playgroud)

这是我的测试效果很好:

test('Authorized - respond with user object', async () => {
  const response = await request(app)
    .post('/api/user/login')
    .send(users.authorized);
  expect(response.body).toHaveProperty('authenticated', true);
});
Run Code Online (Sandbox Code Playgroud)

函数如下getUserInfo所示:

const getUserInfo = async (username, password) => {
  const identity = await axios.post('/user', {username, password});

  return identity;
}
Run Code Online (Sandbox Code Playgroud)

但它在路由器内执行该方法getUserInfo,并且该方法正在进行 REST 调用 - 我想模拟该方法以避免对其他服务的 REST 调用。怎么办呢?

我在 Jest 文档中找到了一个模拟实现函数https://jestjs.io/docs/en/mock-function-api.html#mockfnmockimplementationfn

但是我如何在超级测试中模拟 func 呢?

Ten*_*eff 6

您可以在测试顶部使用 jest 的自动模拟

像这样:

jest.mock('./path/to/userService');

// and include it as well in your test
const userService = require('./path/to/userService');
Run Code Online (Sandbox Code Playgroud)

它将生成整个模块的模拟,并且每个函数都将被替换为jest.fn()没有实现

然后根据 userService 如果它只是一个对象,它的getUserInfo方法将是 jest.fn() 并且您可以像这样设置它的返回值:

// resolved value as it should return a promise
userService.getUserInfo.mockResolvedValue(mockIdentity);
Run Code Online (Sandbox Code Playgroud)

并且模拟身份必须看起来像这样:

const mockIdentity = {
      authenticated: true,
      tenants: [
        {
          id: "x12",
          mockInfo: "mock-info-value"
        }
      ],
      mother: "Superwoman",
      father: "Superman"
    })
  }
Run Code Online (Sandbox Code Playgroud)