【问题标题】:stubbing a function using jest使用 jest 存根函数
【发布时间】:2017-12-28 18:29:06
【问题描述】:

有没有办法使用 jest API 来存根函数? 我习惯于使用 sinon 存根,在那里我可以为来自我测试单元的任何函数调用编写带有存根的单元测试 - http://sinonjs.org/releases/v1.17.7/stubs/

例如-

sinon.stub(jQuery, "ajax").yieldsTo("success", [1, 2, 3]);

【问题讨论】:

  • 你找到如何用 Jest 解决这个问题了吗?你能举个例子吗?

标签: unit-testing mocking jestjs sinon


【解决方案1】:

对于jest,您应该使用jest.spyOn

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

完整示例:

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

您可以在codesandboxhttps://codesandbox.io/s/018x609krw?expanddevtools=1&module=%2Findex.test.js&view=editor 上试用现场示例

【讨论】:

  • const spy = jest .spyOn(jQuery, "ajax") .mockImplementation(({ success }) => success(payload));
  • @emj365 我刚刚尝试过这种方式并收到了TypeError: success is not a function。你可以在这里玩它:codesandbox.io/s/kkq2377ll5。只需取消注释 12-14 行即可。
【解决方案2】:

Jest provides jest.fn(),它具有一些基本的模拟和存根功能。

如果您对 sinon 有经验且熟悉,您仍然可以创建使用 sinon 测试替身的基于 Jest 的测试。但是,您将失去内置 Jest 匹配器(例如 expect(myStubFunction).toHaveBeenCalled())的便利性。

【讨论】:

  • 谢谢。是否像 sinon.stub.restore 一样可恢复?文档示例对我来说并不是很清楚。似乎您只能模拟整个模块,然后在其中模拟一个函数 + 他们提到了某种自动模拟选项?
【解决方案3】:

通过使用mockReturnValue 和jquery 的$.Deferred,我能够完全分出jquery。这使我可以手动解决我的 ajax 调用,然后函数的其余部分将继续(并且 .done().success() 等的任何链接都将执行。

例子:

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

myClass.executeAjaxFunction();

const return_val = 7;

deferred.resolve(return_val)

如果我有类似的功能

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

下面的测试将通过

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

当然 - 如果您尝试存根非 jquery 函数,您可以跳过此答案的延迟部分。我遇到了这个处理 ajax 的问题,并提出了这个解决方案,作为一种测试函数的方法,该函数在使用 Jest 完成 ajax 调用后执行操作。

【讨论】:

    【解决方案4】:

    做以下两件事,让它为我工作。

    1. 添加 __esModule:true 为我解决了这个问题。

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

    2. 将模拟部分移到描述之前。 (就在导入之后。)

      //把它移到describe之前-> jest.mock(...); describe('', ...);

    希望这对某人有所帮助。

    【讨论】:

      猜你喜欢
      • 2017-06-03
      • 2018-12-15
      • 2015-09-23
      • 2019-06-10
      • 2020-03-28
      • 2021-02-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多