Q:

Is there a way to pass parameters to a mock function?

using jest to unit test, I have the following line:
jest.mock('../../requestBuilder');

and in my folder, i have a 
__mocks__

subfolder where my mock requestBuilder.js is.  My jest unit test correctly calls my mock requestBuilder.js correctly.  Issue is, my requestBuilder is mocking an ajax return, so I want to be able to determine if I should pass back either a successful or failure server response.  Ideally I want to pass a parameter into my mock function to determine if "ajaxSuccess: true/false".  How can I do this?  Thank you

A:

You don't want to pass a parameter into your mock function, the parameters that are passed to your mock function should be controlled by the piece of code that you are testing. What you want to do is change the mocking behavior between executions of the mock function.
Let's assume that you're trying to test this snippet of code:
// getStatus.js

const requestBuilder = require('./requestBuilder');

module.exports = () => {
    try {
        const req = requestBuilder('http://fake.com/status').build();
        if (req.ajaxSuccess) {
            return {status: 'success'};
        } else {
            return {status: 'failure'}
        }
    } catch (e) {
        return {status: 'unknown'};
    }
};

We want to test that getStatus uses the requestBuilder properly, not that the builder.build() method works correctly. Verifying builder.build() is the responsibility of a separate unit test. So we create a mock for our requestBuilder as follows:
// __mocks__/requestBuilder.js

module.exports = jest.fn();

This mock simply sets up the mock function, but it does not implement the behavior. The behavior of the mock should defined in the test. This will give you find grained control of the mocking behavior on a test-by-test basis, rather than attempting to implement a mock that supports every use case (e.g. some special parameter that controls the mocking behavior).
Let's implement some tests using this new mock:
// getStatus.spec.js

jest.mock('./requestBuilder');

const requestBuilder = require('./requestBuilder');
const getStatus = require('./getStatus');

describe('get status', () => {

    // Set up a mock builder before each test is run
    let builder;
    beforeEach(() => {
        builder = {
            addParam: jest.fn(),
            build: jest.fn()
        };
        requestBuilder.mockReturnValue(builder);
    });

    // every code path for get status calls request builder with a hard coded URL,
    // lets create an assertion for this method call that runs after each test execution.
    afterEach(() => {
        expect(requestBuilder).toHaveBeenCalledWith('http://fake.com/status');
    });

    it('when request builder creation throws error', () => {
        // Override the mocking behavior to throw an error
        requestBuilder.mockImplementation(() => {
            throw new Error('create error')
        });
        expect(getStatus()).toEqual({status: 'unknown'});
        expect(builder.build).not.toHaveBeenCalled();
    });

    it('when build throws an error', () => {
        // Set the mocking behavior to throw an error
        builder.build.mockImplementation(() => {
            throw new Error('build error')
        });
        expect(getStatus()).toEqual({status: 'unknown'});
        expect(builder.build).toHaveBeenCalled();
    });

    it('when request builder returns success', () => {
        // Set the mocking behavior to return ajaxSuccess value
        builder.build.mockReturnValue({ajaxSuccess: true});
        expect(getStatus()).toEqual({status: 'success'});
        expect(builder.build).toHaveBeenCalled();
    });

    it('when request builder returns failure', () => {
        // Set the mocking behavior to return ajaxSuccess value
        builder.build.mockReturnValue({ajaxSuccess: false});
        expect(getStatus()).toEqual({status: 'failure'});
        expect(builder.build).toHaveBeenCalled();
    });
});

