Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jest spyOn to mock implementation only on second call and the third call

I have a function that I want to mock only on the second call and third call but use the default implementation on the first call. I have looked at Jest documentation and there's a function mockImplementationOnce that I could use to mock the implementation for a single call.

Is there a function that I could use such that it will use default implementation for the first call and only mock the second and third call?

let functionCalls = 0;
const database = {
  fetchValues() {
    fetchValues();
    fetchValues();
  },
};
jest.spyOn(database, 'fetchValues')
.useDefaultImplementation() // <-- is there such a function?
.mockImplementationOnce(() => 42)
.mockImplementationOnce(() => 42)
like image 571
Stanley Avatar asked Apr 27 '20 01:04

Stanley


People also ask

How do you use spyOn function in Jest?

To spy on an exported function in jest, you need to import all named exports and provide that object to the jest. spyOn function. That would look like this: import * as moduleApi from '@module/api'; // Somewhere in your test case or test suite jest.

Does Jest spyOn mock?

Before every function is run in the file, jest will mock , and after every , jest will restore the function to its original implementation. Using the hooks for setup ensures that every test is fresh and independent of each other.

What is the difference between spyOn and mock in Jest?

jest. mock does this automatically for all functions in a module. jest. spyOn does the same thing but allows restoring the original function.


1 Answers

You can use mockImplementation method to mock the default implementation. See mock-implementations

E.g.

const database = {
  fetchValues() {
    return 'real data';
  },
};

describe('61450440', () => {
  afterEach(() => {
    jest.restoreAllMocks();
  });
  it('should pass', () => {
    jest
      .spyOn(database, 'fetchValues')
      .mockImplementation(() => 'default')
      .mockImplementationOnce(() => 'first call')
      .mockImplementationOnce(() => 'second call');

    console.log(
      [database.fetchValues(), database.fetchValues(), database.fetchValues(), database.fetchValues()].join(','),
    );
  });
  it('should pass too', () => {
    jest
      .spyOn(database, 'fetchValues')
      .mockImplementation(() => 'real data')
      .mockImplementationOnce(() => 'real data')
      .mockImplementationOnce(() => 'first call')
      .mockImplementationOnce(() => 'second call');

    console.log(
      [database.fetchValues(), database.fetchValues(), database.fetchValues(), database.fetchValues()].join(','),
    );
  });

  it('should pass 3', () => {
    const fetchValuesSpy = jest.spyOn(database, 'fetchValues');
    console.log('call original fetchValues:', database.fetchValues());
    fetchValuesSpy.mockImplementationOnce(() => 'first call').mockImplementationOnce(() => 'second call');
    console.log('call mocked fetchValues:', database.fetchValues(), database.fetchValues());
    console.log('call original fetchValues again:', database.fetchValues());
  });
});

test results:

 PASS  stackoverflow/61450440/index.test.ts (13.748s)
  61450440
    ✓ should pass (20ms)
    ✓ should pass too (1ms)
    ✓ should pass 3 (12ms)

  console.log stackoverflow/61450440/index.test.ts:15
    first call,second call,default,default

  console.log stackoverflow/61450440/index.test.ts:27
    real data,first call,second call,real data

  console.log stackoverflow/61450440/index.test.ts:34
    call original fetchValues: real data

  console.log stackoverflow/61450440/index.test.ts:36
    call mocked fetchValues: first call second call

  console.log stackoverflow/61450440/index.test.ts:37
    call original fetchValues again: real data

Test Suites: 1 passed, 1 total
Tests:       3 passed, 3 total
Snapshots:   0 total
Time:        15.761s
like image 182
slideshowp2 Avatar answered Oct 20 '22 05:10

slideshowp2