2
votes

Function I want to test is createCarAndDrive() which uses Car module. I'd like to mock one function in the Car module so its actual function is not called but the mock function.

So, the Car function returns two functions gas() and brake(). Car is implemented by using factory function pattern. So those two functions are wrapped in Car and won't be exposed until Car is called.

Is it somehow possible to mock the function brake() to return false?

Here's the implementation.

// Car.js
function Car({ name, model }) {
  function gas(speed) {
    return `${name} ${model} goes forward at a speed of ${speed}km/h`;
  }
  function brake() {
    return true;
  }

  return {
    gas,
    brake,
  };
}

// driver.js
function createCarAndDrive() {
  const car = Car({ name: 'Fiat', model: 'Punto' });
  car.gas(123);
  return car.brake();
}

// driver.test.js
describe('drive', () => {
  beforeEach(() => {
    // How to mock function inside a function?
    jest.mock('./Car', () => ({
      brake: jest.fn().mockImplementation(() => false),
    }));
  });

  test('it should not brake', () => {
    const itHitBreak = createCarAndDrive();
    expect(itHitBreak).toBe(false);
  });
});
2

2 Answers

4
votes

jest.mock factory functions don't work within test functions.

Move jest.mock to the top level scope of your test and it should work:

import { createCarAndDrive } from './driver';

jest.mock('./Car', () => ({
  Car: () => ({
    gas: () => 'mock gas',
    brake: () => false
  })
}));

describe('drive', () => {
  test('it should not brake', () => {
    const itHitBreak = createCarAndDrive();
    expect(itHitBreak).toBe(false);  // Success!
  });
});
0
votes

You can use mockReturnValue(false) with jest to force the return value in your tests.

So in your code it will look like something like:

...
brake: jest.fn().mockReturnValue(false),
...

Here is the mockReturnValue() documentation.