Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

useFaketimers not behaving as a spy function after updating to 27.0.0 #11551

Closed
asthemus opened this issue Jun 9, 2021 · 6 comments
Closed

Comments

@asthemus
Copy link

asthemus commented Jun 9, 2021

🐛 Bug Report

I updated my repository to use jest@27.0.0 and started to get error because of jest.setTimeout not behaving as a spy function anymore.

To Reproduce

created a simple project to demonstrate the issue

app.ts

import {timeoutFn} from './app'
describe('test func', () => {
	test("test timeoutFn", () => {
		jest.useFakeTimers()
		timeoutFn()
		expect(setTimeout).toBeCalled()
	})
})

app.test.js

export const timeoutFn = () => {
	console.log('the first statement')
	global.setTimeout(() => {
		console.log('the second statement')
	}, 1000)
}

Expected behavior

earlier the test should have passed perfectly without any issue but now I get the error

 ● test func › test timeoutFn

    expect(received).toBeCalled()

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

    Received has type:  function
    Received has value: [Function setTimeout]

      18 |                      jest.useFakeTimers()
      19 |                      timeoutFn()
    > 20 |                      expect(setTimeout).toBeCalled()
         |                                         ^
      21 |              })
      22 | })

envinfo

envinfo

  System:
    OS: macOS 10.15.7
    CPU: (16) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
  Binaries:
    Node: 14.15.4 - /usr/local/bin/node
    Yarn: 1.22.10 - /usr/local/bin/yarn
    npm: 6.14.10 - /usr/local/bin/npm
  npmPackages:
    jest: ^27.0.0 => 27.0.4 

Edit:

just checked out release notes to see that with new jest release, it gives option to use jest.useFakeTimers('modern') and jest.useFakeTimers('legacy') even tho legacy works fine now but I face the same error mentioned above while using 'modern'

@Smrtnyk
Copy link

Smrtnyk commented Jun 9, 2021

Thats intended
Check changelog for jest 27

You should spy on global.setTimeout and then assert the calls

@edmundask
Copy link

It's also worth pointing out that a spy should be set up after jest.useFakeTimers, as otherwise your expectations may not pass as intended.

it('calls setInterval', () => {
  jest.useFakeTimers()
  setIntervalSpy = jest.spyOn(global, 'setInterval')

  foobar()

  // Works as intended
  expect(setIntervalSpy).toHaveBeenCalled()
})

vs

it('calls setInterval', () => {
  setIntervalSpy = jest.spyOn(global, 'setInterval')
  jest.useFakeTimers()

  foobar()

  // Expected number of calls: >= 1
  // Received number of calls:    0
  expect(setIntervalSpy).toHaveBeenCalled()
})

@mikl
Copy link

mikl commented Jun 9, 2021

I don’t see where the changelog mentions this change?

I came here from the Jest timers documentation that still has the old (now broken) code, just FYI.

@riderx
Copy link

riderx commented Aug 23, 2021

Even with your code @edmundask i don't get all call like i should.
test Code :

export const timerGame = (callback: any) => {
  console.log('Ready....go!');
  setInterval(() => {
    console.log("Time's up -- stop!");
    callback && callback();
  }, 1000);
}

and the test

import { timerGame } from '../timer';
// test.ts
jest.useFakeTimers();

test('waits 1 second before ending the game', () => {
  const setIntervalSpy = jest.spyOn(global, 'setInterval')
  timerGame(() => {});
  expect(setIntervalSpy).toHaveBeenCalledTimes(0);
  jest.advanceTimersByTime(1000)
  expect(setIntervalSpy).toBeCalled();
  expect(setIntervalSpy).toHaveBeenLastCalledWith(expect.any(Function), 1000);
  expect(setIntervalSpy).toHaveBeenCalledTimes(1);
  jest.advanceTimersByTime(1000)
  jest.advanceTimersByTime(1000)
  expect(setIntervalSpy).toHaveBeenCalledTimes(3);
});

it's always call 1 time only

@SimenB
Copy link
Member

SimenB commented Apr 6, 2022

I don’t see where the changelog mentions this change?

[jest-config, jest-runtime] [BREAKING] Use "modern" implementation as default for fake timers (https://github.com/facebook/jest/pull/10874 & https://github.com/facebook/jest/pull/11197)

I came here from the Jest timers documentation that still has the old (now broken) code, just FYI.

#11974

@SimenB SimenB closed this as completed Apr 6, 2022
@github-actions
Copy link

github-actions bot commented May 7, 2022

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Please note this issue tracker is not a help forum. We recommend using StackOverflow or our discord channel for questions.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 7, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants