0

I have a particular function that needs to be unit tested. This function calls another one which is in the same file. Their implementation looks something like this:

const action1 = () => dispatch => {
  // do something
}

const action2 = () => dispatch => {
  // do something else
  console.log('before')
  dispatch(action1())
  console.log('after')
}

The main one that is giving me trouble is action2 which I cannot figure out how to test whether or not action1 has been called. Here are the different iterations of my test.

Version 1 - using jest.spyOn

One of my attempts is making a jest spy on action1. This is not working, gives me the good ol'

Expected number of calls: >= 1 Received number of calls: 0

import * as MyActions from '../myActions'
import { action1, action2 } from '../myActions'

describe('myActions', () => {
  describe('action1', () => {
    test('should properly run action1', () => {
      // everything is tested and works as expected
    })
  })

  describe('action2', () => {
    test('should properly run action2', () => {
      const action1Spy = jest.spyOn(MyActions, 'action1')
      expect(action1Spy).toHaveBeenCalled() // error here
    })
  })
})

Version 2 - using jest.mock in the action2 describe block

I then try to mock action1 with jest.mock, but since I do actual unit tests for action1, I tried to put it in its describe block. Not sure if this is allowed, but it doesn't matter because it did not work anyway. Got he following error:

Matcher error: received value must be a mock or spy function

The code like this:

import { action1, action2 } from '../myActions'

describe('myActions', () => {
  describe('action1', () => {
    test('should properly run action1', () => {
      // everything is tested and works as expected
    })
  })

  describe('action2', () => {
    jest.mock('../myActions', () => ({
      ...jest.requireActual('../myActions'),
      action1: jest.fn(),
    }))

    test('should properly run action2', () => {
      const action1Spy = jest.spyOn(MyActions, 'action1')
      expect(action1Spy).toHaveBeenCalled() // error here
    })
  })
})

Version 3 - using jest.mock on the file root describe block

As I grow more desperate, I removed the action1 unit tests, and tried to do the above on the file root. But again, I get the error of it never being called. Also... This method may cause problems for action1's unit tests so, even if it did work I am not sure how to get around it.

Expected number of calls: >= 1 Received number of calls: 0

import { action1, action2 } from '../myActions'

jest.mock('../myActions', () => ({
  ...jest.requireActual('../myActions'),
  action1: jest.fn(),
}))

describe('myActions', () => {
  describe('action1', () => {
    test('should properly run action1', () => {
      // skipped for now
    })
  })

  describe.only('action2', () => {
    test.only('should properly run action2', () => {
      const action1Spy = jest.spyOn(MyActions, 'action1')
      expect(action1Spy).toHaveBeenCalled() // error here
    })
  })
})

Anyway, this is where we are at.

I have surrounded my action1 calls with console.logs as you can see above. And indeed they are being logged, so it is supposed to be called.

I do also realize that the call is within a dispatch, but this works just fine in other cases and don't know how else to get around this.

theJuls
  • 5,731
  • 10
  • 56
  • 121

0 Answers0