15

I have a Helper.js file with several helper functions as below that is being used in different components.

    export function buildOptions(elem) { 
        var oList=[];   
        for (var i=0; i < field.length; i++) {
            oList.push (
              <option value={options[i]["id"]}>
                  {options[i][elem]}
              </option>
            )
         }    
         return oList;
      }

      export function B(){
           .....
      }

Here is a component which makes use of the function defined in Helper.js file. I am writing tests for the component and I would like to mock the external function being called here.

    import React from 'react';
    import ReactDOM from 'react-dom';
    import { buildOptions, A} from './Helper.js';

    class DemoComponent extends React.Component {
        constructor(props) {
            super(props);
        }

        add(e, index) {
            ....
        }


        render() {
            var o_list=buildOptions("name");

            return (
               <div>
                  ...
                  <select required className={selectClass}  >
                      {o_list}
                  </select>  
                  ...           
                  <button type="button" onClick={(e) => this.add(e, this.props.index)}>
                        Add 
                  </button>
               </div>
            );
         };
     }

I am new to Jest/Enzyme and I am unable to figure out how to mock the external function buildOptions. I am unable to figure out how to mock the external buildOptions function.Could anyone please help me with this. Here is my test code:

import React from 'react';
import { mount, shallow } from 'enzyme';
import { buildOptions } from '../components/Helper.js';
import DemoComponent from '../components/DemoComponent';

describe('Democomponent', () => {

  it('should render required elements', () => {

    const wrapper = shallow(
       <DemoComponent 
        index={0}/> 
    );
    //
    tests
}); 
Andrea Carraro
  • 9,731
  • 5
  • 33
  • 57
tom
  • 233
  • 1
  • 4
  • 9
  • Might be helpful, about mocking external imports: https://stackoverflow.com/questions/43500235/jest-mock-a-function-called-inside-a-react-component/43500535#43500535 – Xarvalus Jul 06 '18 at 23:09
  • Thanks for sharing. I was able to get it working with the second solution. Ideally I would want to do it the way mentioned in the accepted answer.But my mocks are not being picked up. Could you please help? – tom Jul 07 '18 at 02:49

2 Answers2

35

Since you want to mock a named exported function, there is a special trick for that which involves importing all named exports with an * before your tests.

// your test file
import * as Helper from './Helper.js';

const originalBuildOptions = Helper.buildOptions;
Helper.buildOptions = jest.fn();

beforeEach(() => {
  jest.clearAllMocks();
  // Reset to original implementation before each test
  Helper.buildOptions.mockImplementation(originalBuildOptions);
});

test('my test', () => {
  // Mock for this test only (will be restored by next `beforeEach` call)
  Helper.buildOptions.mockImplementation(() => 'your mock');
}); 
Andrea Carraro
  • 9,731
  • 5
  • 33
  • 57
  • That works ! Is there any way to unmock the function and use the real implementation for few testcases? – tom Jul 07 '18 at 18:25
  • Updated example. You might also want to have a look to this answers to a few different approaches: https://stackoverflow.com/questions/48790927/how-to-change-mock-implementation-on-a-per-single-test-basis-jestjs – Andrea Carraro Jul 07 '18 at 23:36
  • 10
    Boy what a fussy syntax. Thanks @AndreaCarraro! – benjamin.keen Dec 20 '19 at 22:57
  • You saved my life dude, this still works in 03/2022 – leshugo33 Mar 18 '22 at 22:11
  • I got that error: Cannot redefine property: buildOptions. In my case, there are index.ts file and it's content contains export * from other file (ex: export * from './slack'; export * from './time';) – Do Minh Phong Jul 15 '22 at 07:29
1

You can also mock default and named exports directly on import. The official jest documentation uses this method as of 2023. Updating to your use case:

// Your test file
import { buildOptions } from './Helper.js';
jest.mock('./Helper.js', () => {
    const originalModule = jest.requireActual('./Helper.js');

    // Mock any module exports here
    return {
        __esModule: true,
        ...originalModule,
        // default: jest.fn(() => 'mocked default export example'),
        // Named export mocks
        buildOptions: jest.fn(),
    };
});

This also works for installed packages as well. For example, I often override specific react-router hooks like useSubmit using the same style of import.

See the official documentation on partial jest named mocks here: https://jestjs.io/docs/mock-functions#mocking-partials

Chris
  • 51
  • 4