Jest mock not resolving to each injected value

☆樱花仙子☆ 提交于 2021-01-29 13:39:51

问题


I'm trying to test a Firebase cloud function named myCloudFn in my functions/send.js module. My tests are in functions/test/send.spec.js:

// send.js
const admin = require('firebase-admin');

async function myCloudFn (email) {
  const authUser = await admin.auth().getUserByEmail(email);
  return authUser;
}

module.exports = { myCloudFn };
// send.spec.js
const send = require('../send.js');

jest.mock('firebase-admin', () => ({
  auth: () => ({
    getUserByEmail: jest.fn()
      .mockResolvedValueOnce({ uid: 'foo-bar' })
      .mockResolvedValueOnce(null),
  }),
}));

describe('send.js', () => {
  it('returns authUser from myCloudFn()', async () => {
    const email = 'foo@bar.com';
    const responseOptions = [{ uid: 'foo-bar' }, null];
    const responsePromises = responseOptions.map(() => send.myCloudFn(email));
    const responses = await Promise.all(responsePromises);
    expect(responses[0]).toStrictEqual(responseOptions[0]);
    expect(responses[1]).toStrictEqual(responseOptions[1]);
  });
});

The test passes on the first assertion, but fails on the second. The test returns the same { uid: 'foo-bar' } object both times, but I want the test response value to be null the second time. What am I missing?


回答1:


A new getUserByEmail spy is created on each auth call, it isn't called more than once.

Instead, it should be:

const mockGetUserByEmail = jest.fn();
jest.mock('firebase-admin', () => ({
  auth: () => ({
    getUserByEmail: mockGetUserByEmail
  })
}));

...
mockGetUserByEmail
  .mockResolvedValueOnce({ uid: 'foo-bar' })
  .mockResolvedValueOnce(null);
const responsePromises = responseOptions.map(() => send.myCloudFn(email));
...



回答2:


You can mock the resolved value once of the getUserByEmail method for each test case.

E.g.

send.js:

const admin = require('firebase-admin');

async function myCloudFn(email) {
  const authUser = await admin.auth().getUserByEmail(email);
  return authUser;
}

module.exports = { myCloudFn };

send.test.js:

const { myCloudFn } = require('./send');
const admin = require('firebase-admin');

jest.mock(
  'firebase-admin',
  () => {
    const mAdmin = {
      auth: jest.fn().mockReturnThis(),
      getUserByEmail: jest.fn(),
    };
    return mAdmin;
  },
  { virtual: true },
);

describe('send.js', () => {
  afterAll(() => {
    jest.resetAllMocks();
  });
  it('should returns authUser from myCloudFn()', async () => {
    admin.auth().getUserByEmail.mockResolvedValueOnce({ uid: 'foo-bar' });
    const actual = await myCloudFn();
    expect(actual).toEqual({ uid: 'foo-bar' });
  });
  it('should return null', async () => {
    admin.auth().getUserByEmail.mockResolvedValueOnce(null);
    const actual = await myCloudFn();
    expect(actual).toBeNull();
  });
});

unit test result:

 PASS  src/stackoverflow/64575307/send.test.js (14.349s)
  send.js
    ✓ should returns authUser from myCloudFn() (11ms)
    ✓ should return null (3ms)

----------|----------|----------|----------|----------|-------------------|
File      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files |      100 |      100 |      100 |      100 |                   |
 send.js  |      100 |      100 |      100 |      100 |                   |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        17.321s


来源:https://stackoverflow.com/questions/64575307/jest-mock-not-resolving-to-each-injected-value

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!