我可以使用Jest模拟具有特定参数的函数吗?

2022-08-30 05:22:59

我想用Jest模拟一个函数,但前提是用特定的参数调用它,例如:

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)

Ruby 的 RSpec 库中还实现了类似的功能:

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)

我试图在测试中实现的是更好的解耦,假设我想测试一个依赖于: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

我知道有一种方法可以通过做这样的事情来实现这一点:

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");

但是,如果我们有一些糖功能来简化它,那就太好了。

这听起来合理吗?我们在Jest中已经有了这个功能吗?

感谢您的反馈。


答案 1

我发现了我的一位同事最近写的这个库: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!');

这是库:https://github.com/timkindberg/jest-when


答案 2

jest-when提到可能是最好的选择。STeve Shary

如果你不想安装一个新的库,当你不关心原来的功能时,这里有一个单行解决方案:

sum.mockImplementation((x, y) => x === 1 && y === 2 && "my-return-value")