Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

stubbing a function using jest

is there a way to stub a function using jest API? I'm used to working with sinon stub, where I can write unit-tests with stubs for any function call coming out of my tested unit- http://sinonjs.org/releases/v1.17.7/stubs/

for example-

sinon.stub(jQuery, "ajax").yieldsTo("success", [1, 2, 3]);
like image 439
Mattan Bitner Avatar asked Jul 22 '17 20:07

Mattan Bitner


People also ask

How do you mock a function in Jest?

There are two ways to mock functions: Either by creating a mock function to use in test code, or writing a manual mock to override a module dependency.

How do you test a function is called in Jest?

How to check if a function was called correctly with Jest? To check if a function was called correctly with Jest we use the expect() function with specific matcher methods to create an assertion. We can use the toHaveBeenCalledWith() matcher method to assert the arguments the mocked function has been called with.

What is stub in Jest testing?

A stub is a small piece of code that takes the place of another component during testing. The benefit of using a stub is that it returns consistent results, making the test easier to write. And you can run tests even if the other components are not working yet.


4 Answers

With jest you should use jest.spyOn:

jest
  .spyOn(jQuery, "ajax")
  .mockImplementation(({ success }) => success([ 1, 2, 3 ]));

Full example:

const spy = jest.fn();
const payload = [1, 2, 3];

jest
  .spyOn(jQuery, "ajax")
  .mockImplementation(({ success }) => success(payload));

jQuery.ajax({
  url: "https://example.api",
  success: data => spy(data)
});

expect(spy).toHaveBeenCalledTimes(1);
expect(spy).toHaveBeenCalledWith(payload);

You can try live example on codesandbox: https://codesandbox.io/s/018x609krw?expanddevtools=1&module=%2Findex.test.js&view=editor

like image 104
Ilya Zub Avatar answered Oct 19 '22 14:10

Ilya Zub


Jest provides jest.fn(), which has some basic mocking and stubbing functionality.

If you're experienced and comfortable with sinon you could still create Jest-based tests which use sinon test doubles. However you'll lose the convenience of built in Jest matchers such as expect(myStubFunction).toHaveBeenCalled().

like image 28
Pete Hodgson Avatar answered Oct 19 '22 14:10

Pete Hodgson


Doing following two thing, got it working for me.

  1. Adding __esModule:true fixed this issue for me.

    jest.mock('module',()=>({ __esModule: true, default: jest.fn() }));

  2. Moving the mocking part before the describe. (Just after the imports.)

    //moving it to before the describe -> jest.mock(...); describe('', ...);

Hope this helps somebody.

like image 2
Ankur Marwaha Avatar answered Oct 19 '22 15:10

Ankur Marwaha


I was able to sub out jquery entirely by using mockReturnValue and jquery's $.Deferred. This allowed me to manually resolve my ajax calls and then the rest of the function would continue (and any chaining of .done() or .success() etc would execute.

Example:

const deferred = new $.Deferred();
$.ajax = jest.fn().mockReturnValue(deferred);

myClass.executeAjaxFunction();

const return_val = 7;

deferred.resolve(return_val)

Then if I have a function like

$.ajax({
    type: 'GET',
    url: '/myurl'
}).done((val) => {
    window.property = val;
});

The following test will pass

it('should set my property correctly', () => {
    expect(window.property).toBe(7);
});

Of course- you can skip the deferred part of this answer if you are trying to stub a non-jquery function. I came across this question that dealt with ajax and came up with this solution as a way to test a function that executes actions after an ajax call is complete using Jest.

like image 2
chevybow Avatar answered Oct 19 '22 15:10

chevybow