admin管理员组

文章数量:1404763

I'm trying to test a router in Node.js app with Jest + Supertest, but my router is making a call to service, which is calling the endpoint:

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);
  }
});

This is my test that works well:

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);
});

this is how getUserInfo function looks like:

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

  return identity;
}

but it executes the method getUserInfo inside a router and this method is making a REST call - I want to mock this method in order to avoid REST calls to other services. How it could be done?

I've found a mockImplementation function in Jest docs .html#mockfnmockimplementationfn

but how I can mock func inside a supertest testing?

I'm trying to test a router in Node.js app with Jest + Supertest, but my router is making a call to service, which is calling the endpoint:

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);
  }
});

This is my test that works well:

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);
});

this is how getUserInfo function looks like:

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

  return identity;
}

but it executes the method getUserInfo inside a router and this method is making a REST call - I want to mock this method in order to avoid REST calls to other services. How it could be done?

I've found a mockImplementation function in Jest docs https://jestjs.io/docs/en/mock-function-api.html#mockfnmockimplementationfn

but how I can mock func inside a supertest testing?

Share Improve this question edited Apr 2, 2020 at 15:31 Karen asked Apr 2, 2020 at 14:45 KarenKaren 1,4295 gold badges27 silver badges50 bronze badges 7
  • I guess that you start a "real" api server before these tests, that means that your tests are running in a different node context (separate process), therefore there is no why that tests can mock something in it. Am I right? – felixmosh Commented Apr 2, 2020 at 15:16
  • I've added getUserInfo to the description – Karen Commented Apr 2, 2020 at 15:21
  • I want to mock this function in order not to make calls to external API – Karen Commented Apr 2, 2020 at 15:22
  • Is my assumption is correct? you start an API server & run the tests? – felixmosh Commented Apr 2, 2020 at 15:31
  • no, 'API server' is the external service – Karen Commented Apr 2, 2020 at 15:32
 |  Show 2 more ments

1 Answer 1

Reset to default 6

You can use jest's auto mocking at the top of your test

like so:

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

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

it will generate a mock of the entire module and every function will be replaced with jest.fn() with no implementation

and then depending on the userService if it's just an object it's getUserInfo method will be a jest.fn() and you can set it's return value like this:

// resolved value as it should return a promise
userService.getUserInfo.mockResolvedValue(mockIdentity);

and the mockIdentity will have to look something like this:

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

本文标签: javascriptHow to mock a method inside Express router Jest testStack Overflow