Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I mock functions with specific arguments using Jest?

I want to mock a function with Jest, but only if it is called with specific arguments, for example:

function sum(x, y) {   return x + y; }      // mock sum(1, 1) to return 4 sum(1, 1) // returns 4 (mocked) sum(1, 2) // returns 3 (not mocked) 

There is a similar feature implemented in Ruby's RSpec library:

class Math   def self.sum(x, y)     return x + y   end end  allow(Math).to receive(:sum).with(1, 1).and_return(4) Math.sum(1, 1) # returns 4 (mocked) Math.sum(1, 2) # returns 3 (not mocked) 

What I'm trying to achieve in my tests is a better decoupling, let's say I want to test a function that relies on sum:

function sum2(x) {   return sum(x, 2); }  // I don't want to depend on the sum implementation in my tests,  // so I would like to mock sum(1, 2) to be "anything I want",  // and so be able to test:  expect(sum2(1)).toBe("anything I want");  // If this test passes, I've the guarantee that sum2(x) is returning // sum(x, 2), but I don't have to know what sum(x, 2) should return 

I know that there is a way to implement this by doing something like:

sum = jest.fn(function (x, y) {   if (x === 1 && y === 2) {     return "anything I want";   } else {     return sum(x, y);   } });  expect(sum2(1)).toBe("anything I want"); 

But it would be nice if we had some sugar function to simplify it.

Does it sounds reasonable? Do we already have this feature in Jest?

Thanks for your feedback.

like image 602
Nícolas Iensen Avatar asked Jan 17 '17 12:01

Nícolas Iensen


People also ask

How do you mock a specific function in Jest?

Another approach to mock a particular function from an imported module is to use the jest. spyOn function. The API for this function seems to be exactly what we need for our use case, as it accepts an entire module and the particular export that should be spied on.

Is useful when you want to mock functions in certain test?

mockReset() does, and also restores the original (non-mocked) implementation. This is useful when you want to mock functions in certain test cases and restore the original implementation in others.

Can I mock a variable in Jest?

If you need to mock a global variable for all of your tests, you can use the setupFiles in your Jest config and point it to a file that mocks the necessary variables. This way, you will have the global variable mocked globally for all test suites.


2 Answers

I found this library that a colleague of mine wrote recently: jest-when

import { when } from 'jest-when';  const fn = jest.fn(); when(fn).calledWith(1).mockReturnValue('yay!');  const result = fn(1); expect(result).toEqual('yay!'); 

Here's the library: https://github.com/timkindberg/jest-when

like image 157
STeve Shary Avatar answered Oct 08 '22 04:10

STeve Shary


jest-when mentioned by STeve Shary is probably the best option.

If you don't want to install a new library, when you don't care about the original function, here's a one-line solution:

sum.mockImplementation((x, y) => x === 1 && y === 2 && "my-return-value") 
like image 33
André Willik Valenti Avatar answered Oct 08 '22 02:10

André Willik Valenti