Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jest Mock module per test

I am quite confused with mocking in Jest an how to unit test the implementations. The thing is i want to mock different expected behaviours.

Is there any way to achieve this? as imports can be only on the top of the file and to be able to mock something it must be declared before the import. I have also tried to pass a local function so I could overwrite the behaviour but jest complains you are not allowed to pass anything local.

jest.mock('the-package-to-mock', () => ({
  methodToMock: jest.fn(() => console.log('Hello'))
}));

import * as theThingToTest from '../../../app/actions/toTest'
import * as types from '../../../app/actions/types'

it('test1', () => {
  expect(theThingToTest.someAction().type).toBe(types.SOME_TYPE)
})

it('test2', () => {
  //the-package-to-mock.methodToMock should behave like something else
  expect(theThingToTest.someAction().type).toBe(types.SOME_TYPE)
})

internally as you can imagine theThingToTest.someAction() uses the-package-to-mock.methodToMock

like image 489
Kanekotic Avatar asked Jul 10 '17 07:07

Kanekotic


People also ask

What are module mocks in jest?

Module mocks are a powerful tool to write unit tests with Jest. They allow you to isolate the code under test from its dependencies, leading to focused, less brittle tests. But, as many other powerful tools, module mocks can be tricky at times. In this post we’ll explore how to mock different values for the same module in different tests.

How to mock the Lang dependency in jest?

You can use jest.mock (line 4) to mock the lang dependency. In the example above, the mock module has a current field which is set to a mock function. You want to test both branches of hello, so you use mockReturnValueOnce to make the mock function return "GL" in the first invocation, and "EN" in the second one.

What happens when automock is set to true in jest?

However, when automock is set to true, the manual mock implementation will be used instead of the automatically created mock, even if jest.mock ('moduleName') is not called. To opt out of this behavior you will need to explicitly call jest.unmock ('moduleName') in tests that should use the actual module implementation.

How do I write a jest unit test for Hello?

Writing a unit test for hello involves mocking the lang dependency in order to control the current language: You can use jest.mock (line 4) to mock the lang dependency. In the example above, the mock module has a current field which is set to a mock function.


2 Answers

You can mock with a spy and import the mocked module. In your test you set how the mock should behave using mockImplementation:

jest.mock('the-package-to-mock', () => ({
  methodToMock: jest.fn()
}));
import { methodToMock } from 'the-package-to-mock'

it('test1', () => {
  methodToMock.mockImplementation(() => 'someValue')
})

it('test2', () => {
  methodToMock.mockImplementation(() => 'anotherValue')
})
like image 73
Andreas Köberle Avatar answered Oct 20 '22 11:10

Andreas Köberle


I use the following pattern:

'use strict'

const packageToMock = require('../path')

jest.mock('../path')
jest.mock('../../../../../../lib/dmp.db')

beforeEach(() => {
  packageToMock.methodToMock.mockReset()
})

describe('test suite', () => {
  test('test1', () => {
    packageToMock.methodToMock.mockResolvedValue('some value')
    expect(theThingToTest.someAction().type).toBe(types.SOME_TYPE)

  })
  test('test2', () => {
    packageToMock.methodToMock.mockResolvedValue('another value')
    expect(theThingToTest.someAction().type).toBe(types.OTHER_TYPE)
  })
})

Explanation:

You mock the class you are trying to use on test suite level, make sure the mock is reset before each test and for every test you use mockResolveValue to describe what will be return when mock is returned

like image 16
Tal Joffe Avatar answered Oct 20 '22 11:10

Tal Joffe