admin管理员组

文章数量:1289911

I'm trying to mock a function and not sure what i'm doing wrong here. I have this function "getGroups"

getGroups:

export const getGroups = async () => {
  try {
    const groupApiUrl = getDashboardPath(GROUPS_TAB_INDEX);
    const data = await fetch(groupApiUrl, { cache: 'force-cache' });
    const userData = await data.json();
    return userData;
  } catch (error) {
    throw Error(error);
  }
};

___mocks___/getGroups.js:

export default async () => {
  return {
    groups: [
      { id: 1, name: 'Data1' },
      { id: 2, name: 'Data2' }
    ]
  };
};

getGroups.test.js:

jest.mock('./getGroups.js');
// eslint-disable-next-line import/first
import { getGroups } from './getGroups';

const fakeRespose = {
  groups: [
    { id: 1, name: 'Data1' },
    { id: 2, name: 'Data2' }
  ]
};

describe('getGroups', () => {
  it('returns data', async () => {
    const data = await getGroups();
    console.log('DATA', data);  <---- UNDEFINED?
    expect(data).toBeDefined();
    expect(data).toMatchObject(fakeRespose);
  });

  it('handles error', async () => {
    // const data = await getGroups();
    await getGroups().toThrow('Failed');
  });
});

I'm trying to mock a function and not sure what i'm doing wrong here. I have this function "getGroups"

getGroups:

export const getGroups = async () => {
  try {
    const groupApiUrl = getDashboardPath(GROUPS_TAB_INDEX);
    const data = await fetch(groupApiUrl, { cache: 'force-cache' });
    const userData = await data.json();
    return userData;
  } catch (error) {
    throw Error(error);
  }
};

___mocks___/getGroups.js:

export default async () => {
  return {
    groups: [
      { id: 1, name: 'Data1' },
      { id: 2, name: 'Data2' }
    ]
  };
};

getGroups.test.js:

jest.mock('./getGroups.js');
// eslint-disable-next-line import/first
import { getGroups } from './getGroups';

const fakeRespose = {
  groups: [
    { id: 1, name: 'Data1' },
    { id: 2, name: 'Data2' }
  ]
};

describe('getGroups', () => {
  it('returns data', async () => {
    const data = await getGroups();
    console.log('DATA', data);  <---- UNDEFINED?
    expect(data).toBeDefined();
    expect(data).toMatchObject(fakeRespose);
  });

  it('handles error', async () => {
    // const data = await getGroups();
    await getGroups().toThrow('Failed');
  });
});
Share Improve this question edited Mar 30, 2020 at 18:17 skyboyer 23.8k7 gold badges62 silver badges71 bronze badges asked Mar 30, 2020 at 17:48 BatmanBatman 6,37322 gold badges87 silver badges161 bronze badges 5
  • Is that really what the mocked function looks like? What is {fakeData}? – Pointy Commented Mar 30, 2020 at 17:51
  • No, updated post – Batman Commented Mar 30, 2020 at 17:53
  • Can you try jest.mock('./getGroups');? – Ayush Gupta Commented Mar 30, 2020 at 17:55
  • I tried it and it didn't help – Batman Commented Mar 30, 2020 at 17:57
  • There is difference between the way you return the export in mock file and actual code. May be you can check that. – vishnu sandhireddy Commented Mar 30, 2020 at 18:08
Add a ment  | 

2 Answers 2

Reset to default 4

What are you doing wrong here?

  1. Default export in your mock instead of named as in the implementation

In your implementation you're using named export and you're importing { getGroups } so to make it work you need to change your mock like this

__mocks__\getGroups.js
export const getGroups = async () => {
  return {
    groups: [
      { id: 1, name: 'Data1' },
      { id: 2, name: 'Data2' }
    ]
  };
};

working example


TL;DR

  1. Testing mock

There is no point at all to test mock function. This does not proves your implementation is working. Even if you change your implementation your tests will still pass.

Use mocks only for the dependencies of your implementation

  1. Use jest.genMockFromModule It will create jest.fn() for each of the module's exported methods and will preserve the constants, allowing you to change the return value/implementation for some test cases and will also be able to write assertions if the function have been called
__mocks__\getGroups.js
const mock = jest.genMockFromModule('../getGroups');
mock.getGroups.mockResolvedValue({
  groups: [
    { id: 1, name: 'Data1' },
    { id: 2, name: 'Data2' }
  ]
})

module.exports = mock;
  1. Jest will automatically hoist jest.mock calls (read more...)

So you can safely leave the import statements first and then call jest.mock

From Jest Docs, here's an example of a Mock.

jest.mock('../moduleName', () => {
  return jest.fn(() => 42);
});

// This runs the function specified as second argument to `jest.mock`.
const moduleName = require('../moduleName');
moduleName(); // Will return '42';

In your case data is undefined, because you haven't actually supplied a mocked implementation for the function or the mock hasn't worked and you're still calling the original function.

Example Reference: https://jestjs.io/docs/en/jest-object#jestmockmodulename-factory-options

However, in your simple case you could also solve this with a spy, either jest.spyOn or jest.fn(). Here are two solutions to what you're trying to achieve. You can look at the code and run it here: https://repl.it/repls/FairUnsungMice

UPDATE after ment:

Manual mocks are defined by writing a module in a __mocks__/ subdirectory immediately adjacent to the module. For example, to mock a module called user in the models directory, create a file called user.js and put it in the models/__mocks__ directory. Note that the __mocks__ folder is case-sensitive, so naming the directory __MOCKS__ will break on some systems.

Double check the naming, directory structure & type of exports you've setup - they should match. Also, it's worth checking this out: https://github./facebook/jest/issues/6127 - looks like an open issue with jest. If you need a solution, look at using a different approach as I mentioned.

Reference: https://jestjs.io/docs/en/manual-mocks

本文标签: javascriptJest Mock returns undefined instead of dataStack Overflow