最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How do I change the mock implementation of a function in a mock module in Jest - Stack Overflow

programmeradmin3浏览0评论

I have a utils file that looks something like this

// utils.js
const getNextDate = (startDate) => moment(startDate, 'MMM Do YYYY').startOf('day').add(10, 'days').format('MMM Do YYYY');
const getDisplayName = (user) => {
  if (user.type === 'admin') {
    return 'Admin';
  } else if (user.type === 'guest') {
    return 'Guest'
  } else if(user.type === 'user') {
    return `${user.firstname} ${user.lastname}`
  } else {
    return 'No user'
  }
}

export {
  getNextDate,
  getDisplayName
}

I also have a mock of my utils file in my mocks folder where I implement the mock return values for testing. It looks something like this

// mock/utils.js
export const getNextDate = () => 'Oct 20th 2020';
export const getDisplayName = (user) => user

In my ponent and test, I'm doing something like this

//Component.js
import React from 'react';
import { getNextDate, getDisplayName } from './utils'

export const Component = () => {
  const user = {
    type: 'admin',
    firstname: 'john',
    lastname: 'doe',
  }
  return (
    <div>
      <div>{getDisplayName(user)}</div>
      <div>{getNextDate(moment())}</div>      
    </div>
  )
}

// Component.test.js
import { Component } from '../Component'
jest.mock('./utils', () => require('./mock/utils'));

describe('Component', () => {
  beforeEach(() => {
    wrapper = shallow(
      <Component />
    );
  });

  it('renders next date', () => {
      // At this point, I want to change the mock return value of getNextDate to Dec 25th 2020 without changing it in mock/utils.js as other tests are using that value
      expect(wrapper.find('.date').text()).toEqual('Dec 25th 2020');
  });
});

However, in one of the test cases, I'm trying to change the mock implementation of getNextDate. How do I get this done since I can't just call getNextDate.mockImplementation() directly?

I have a utils file that looks something like this

// utils.js
const getNextDate = (startDate) => moment(startDate, 'MMM Do YYYY').startOf('day').add(10, 'days').format('MMM Do YYYY');
const getDisplayName = (user) => {
  if (user.type === 'admin') {
    return 'Admin';
  } else if (user.type === 'guest') {
    return 'Guest'
  } else if(user.type === 'user') {
    return `${user.firstname} ${user.lastname}`
  } else {
    return 'No user'
  }
}

export {
  getNextDate,
  getDisplayName
}

I also have a mock of my utils file in my mocks folder where I implement the mock return values for testing. It looks something like this

// mock/utils.js
export const getNextDate = () => 'Oct 20th 2020';
export const getDisplayName = (user) => user

In my ponent and test, I'm doing something like this

//Component.js
import React from 'react';
import { getNextDate, getDisplayName } from './utils'

export const Component = () => {
  const user = {
    type: 'admin',
    firstname: 'john',
    lastname: 'doe',
  }
  return (
    <div>
      <div>{getDisplayName(user)}</div>
      <div>{getNextDate(moment())}</div>      
    </div>
  )
}

// Component.test.js
import { Component } from '../Component'
jest.mock('./utils', () => require('./mock/utils'));

describe('Component', () => {
  beforeEach(() => {
    wrapper = shallow(
      <Component />
    );
  });

  it('renders next date', () => {
      // At this point, I want to change the mock return value of getNextDate to Dec 25th 2020 without changing it in mock/utils.js as other tests are using that value
      expect(wrapper.find('.date').text()).toEqual('Dec 25th 2020');
  });
});

However, in one of the test cases, I'm trying to change the mock implementation of getNextDate. How do I get this done since I can't just call getNextDate.mockImplementation() directly?

Share Improve this question edited Oct 14, 2020 at 15:50 joel_ace asked Oct 14, 2020 at 9:58 joel_acejoel_ace 1332 silver badges11 bronze badges 5
  • I can't just call b.mockImplementation() directly - is that because you didn't use jest.fn for mocks? Use it then. – Estus Flask Commented Oct 14, 2020 at 10:44
  • the function b is not defined in the test file so I'll get a ReferenceError. Though it is part of the imported utils file, it's not a named import – joel_ace Commented Oct 14, 2020 at 11:06
  • 1 Please, provide stackoverflow./help/mcve that can reproduce the problem. Don't truncate imports and exports as they are relevant. Though it is part of the imported utils file, it's not a named import - but it's named export in "utils file that looks something like this". – Estus Flask Commented Oct 14, 2020 at 11:45
  • I've updated the question – joel_ace Commented Oct 14, 2020 at 15:31
  • ReferenceError was there because getNextDate wasn't imported. But even if it were, it should have been Jest spy to change mock implementation. – Estus Flask Commented Oct 14, 2020 at 20:47
Add a ment  | 

1 Answer 1

Reset to default 5

jest.mock('./utils', () => require('./mock/utils')) reinvents existing Jest functionality, __mocks__ manual mocks.

It should be __mocks__/utils.js at the same level as original module and use Jest spies in order to make the implementation changeable:

export const getNextDate = jest.fn(() => ...);
export const getDisplayName = jest.fn(() => ...);

Considering that __mocks__ provides default mocks, they shouldn't be overridden with mockImplementation for specific tests because this will affect subsequent tests. Instead it should be mocked for specific calls with *Once. For a wrapper that was specified in beforeEach and is mon to several tests:

import { getNextDate } from './utils';
jest.mock('./utils')

...

  beforeEach(() => {
    wrapper = shallow(<Component />); // uses default mock
  });

  it('renders next date', () => {
    getNextDate.mockReturnValueOnce(...);
    wrapper.setProps({}); // update with new mock
    expect(wrapper.find('.date').text()).toEqual('Dec 25th 2020');
  });
发布评论

评论列表(0)

  1. 暂无评论