How to mock a method inside Express router Jest test?

Viewed 3943

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?

1 Answers

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"
    })
  }
Related