简体   繁体   English

如何用玩笑模拟回调函数

[英]How to mock callback functions with jest

I'm trying to mock a custom function with jest but I'm having problems with it.我正在尝试用 jest 模拟自定义函数,但我遇到了问题。

This is my function:这是我的功能:

export const resizeImage = (file, fileName, callback) => {
  const MAX_WIDTH = avatarImage.maxWidth;
  const MAX_HEIGHT = avatarImage.maxHeight;
  const img = document.createElement('img');
  img.src = window.URL.createObjectURL(file);
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');

  img.onload = () => {
    const sizes = internalResizeImage(img, MAX_WIDTH, MAX_HEIGHT);

    canvas.width = sizes.width;
    canvas.height = sizes.height;
    ctx.drawImage(img, 0, 0, sizes.width, sizes.height);
    return callback(dataURItoFile(canvas.toDataURL(), fileName));
  };
};

I called like this:我是这样打电话的:

resizeImage(acceptedFiles[0], this.props.user.id, (res) => {
  //dostuff
});

In my test I'm mocking it like this:在我的测试中,我像这样嘲笑它:

let mockResizeImage = jest.fn();

jest.mock('../../utilities/imageUtils', () => ({
  resizeImage: () => mockResizeImage
}));

I want mockResizeImage to be a callback and then in my test change the returning values:我希望 mockResizeImage 是一个回调,然后在我的测试中更改返回值:

it('should call handleDrop and accept files', () => {
    //mockResizeImage.mockReturnValue('something');

    const instance = shallow(mockComponent()).instance();
    const acceptFilesMock = ['test'];

    instance.handleDrop(acceptFilesMock);

    expect(clickSpy).toHaveBeenCalledTimes(1);
  });

If it were a promise, all good, but it's a callback and I don't know what I'm doing wrong.如果这是一个承诺,一切都很好,但这是一个回调,我不知道我做错了什么。

Thanks.谢谢。

You can mock a module with a function that accepts the same parameter as your original one, and instantly call the callback:您可以使用接受与原始参数相同的参数的函数来模拟模块,并立即调用回调:

jest.mock('../../utilities/imageUtils', () => ({
  resizeImage: (file, fileName, callback) => callback('someData')
}));

Btw.顺便提一句。 the way you mock the module in your question can't work because of the way jest.mock works.由于jest.mock工作方式,您在问题中模拟模块的方式jest.mock正常工作。 Even if you write it after the let statement, it will be hoisted to the top of the file when the test is been compiled.即使你写在let语句之后,在编译测试时也会被提升到文件顶部。 So the best way to mock the function with a spy would look like this:因此,使用 spy 模拟该函数的最佳方法如下所示:

import {resizeImage} from '../../utilities/imageUtils'

jest.mock('../../utilities/imageUtils', () => ({
  resizeImage: jest.fn((file, fileName, callback) => callback('someData'))
}));

Now you have the same behaviour as above but you can also test that resizeImage was called with the correct parameters.现在您的行为与上述相同,但您还可以测试是否使用正确的参数调用了resizeImage

As your last parameter is a function you can either just test for the 2 first params like this using mock.calls :由于您的最后一个参数是一个函数,您可以使用mock.calls测试像这样的第 2 个参数:

expect(resizeImage.mock.calls[0][0]).toBe('firstParameter')
expect(resizeImage.mock.calls[0][1]).toBe('secondParameter')

Or use a wildcard for the last parameter when using toBeCalledWith using expect.anything() :或者在使用toBeCalledWith使用expect.anything()时对最后一个参数使用通配符:

expect(resizeImage).toBeCalledWith('firstParameter', 'secondParameter', expect.anything()); 

Make sure when you call the actual function by passing the callback function as one of the arguments, that function is being called from inside the test block like below确保当您通过将回调函数作为参数之一传递来调用实际函数时,该函数是从测试块内部调用的,如下所示

function forEach(items, callback) {
  for (let index = 0; index < items.length; index++) {
    callback(items[index]);
  }
}
const mockCallback = jest.fn((x) => x + 1);

test("fn", () => {
  forEach([0, 1, 2], mockCallback);
  expect(mockCallback.mock.calls.length).toBe(3);
});

And not like below而不像下面

function forEach(items, callback) {
      for (let index = 0; index < items.length; index++) {
        callback(items[index]);
      }
    }
const mockCallback = jest.fn((x) => x + 1);
forEach([0, 1, 2], mockCallback);
    
test("fn", () => {
   expect(mockCallback.mock.calls.length).toBe(3);
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM