skip to Main Content

I am attempting to unit test 2 exported helper functions that both call useContext on my default context value, however I can’t seem to get it working after a lot of looking online.

export const func1 = () => {
    const { key1, key2 } = useContext(MyContext);
    return { key1, key2 };
}

export const func2 = () => {
    const { key2 } = useContext(MyContext);

    // some more complex stuff here 
}

Test

import React, { useContext } from 'react';

...

it('with mock', () => {
    jest.mock('react', () => ({
      ...jest.requireActual('react'),
      useContext: (ctx: any) => mockUseContext(ctx)
    }));

    useContext.mockImplementation(ctx => ({ someKey: 'someVal' }));

    // Property 'mockImplementation' does not exist on type ' (context: Context ) => T

    expect(func1()).toBe({ someKey: 'someVal' });
});

it('with spyOn', () => {
     jest.spyOn(React, 'useContext').mockImplementation(() => ({ someKey: 'someVal' }));

     expect(func1()).toBe({ someKey: 'someVal' });
});

2

Answers


  1. When unit testing helper functions that use the useContext hook, you need to mock the useContext function to provide your own mock values. Here’s how you can do it:

    import React, { useContext } from 'react';
    
    jest.mock('react', () => ({
      ...jest.requireActual('react'),
      useContext: jest.fn(),
    }));
    
    const mockContextValue = {
      key1: 'value1',
      key2: 'value2',
    };
    
    describe('Helper Functions', () => {
      beforeEach(() => {
        useContext.mockReturnValue(mockContextValue);
      });
    
      it('should return the correct values from func1', () => {
        const { func1 } = require('./yourHelperFunctionsFile');
        const result = func1();
        expect(result).toEqual(mockContextValue);
      });
    
      it('should work with func2', () => {
        const { func2 } = require('./yourHelperFunctionsFile');
        // Test func2 here
      });
    });
    

    In this example, we use jest.mock to mock the useContext function from React. Then, we set the return value of the useContext mock to mockContextValue, which is an object representing the values you want to use in your tests.

    Inside each test, we import the specific function being tested and call it. In the case of func1, we expect the result to be equal to mockContextValue.

    Note that in order to make the mocking work correctly, you need to make sure you import the functions inside each test case, as shown in the example. This ensures that the mocked version of useContext is used when calling the function.

    Feel free to modify the code as per your needs and add additional assertions and test cases for func2 or any other helper functions you want to test.

    Login or Signup to reply.
  2. See jest.Mocked

    Types of classes, functions, or objects can be passed as type argument to jest.Mocked<Source>. If you prefer to constrain the input type, use: jest.MockedClass<Source>, jest.MockedFunction or jest.MockedObject<Source>.

    import React, { useContext } from 'react';
    
    jest.mock('react', () => ({
        ...(jest.requireActual('react') as typeof import('react')),
        useContext: jest.fn(),
    }));
    
    const useContextMock = useContext as jest.MockedFunction<typeof useContext>;
    
    const MyContext = React.createContext(null);
    const func1 = () => useContext(MyContext);
    
    it('with mock', () => {
        useContextMock.mockImplementation((ctx) => ({ someKey: 'someVal' }));
        expect(func1()).toEqual({ someKey: 'someVal' });
    });
    

    "jest": "^26.6.3"

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search