嘲笑类

时间:2019-04-25 13:37:01

标签: class ecmascript-6 mocking jestjs

鉴于我有一个像这样调用函数doStuff的类:


const myService = require(`./myService`),
    service = new myService();

exports.doStuff = async (callback) => {
    try {
        const data = await service.doOtherStuff(); //I want to mock this

        return callback(null, data);
    } catch (err) {
        callback(new Error(` > feed failed for ${key}, error: ${err}`));
    }
};

我的测试是这样的:

const myClass = require(`../index`);
jest.mock(`./../myService`, () => {
    return function() {
        return {
            doOtherStuff: () => {
                return 1;
            }
        };
    };
});

describe(`service-tests - index`, () => {
        test(`doStuff and test otherStuff`, async () => {
            const result = await myClass.doStuff((err, data) => {
                return data;
            });

            expect(result).toBe(1);
        });
});

我的服务:

class myService{
    constructor() {
        //Do constructor stuff
    }

    async doOtherStuff() {
        //Do other stuff
    }

这可以工作,但是现在我只是对该文件进行了模拟,而不是通过测试。 我需要的是让我的模拟可以逐个测试进行更改,但似乎无法弄清楚它如何与require一起工作。

我尝试只做jest.mock('./../myService')并将mockImplementation放在beforeAll上,但这会使我的函数像自动模拟一样被模拟,返回 undefined

有人做过吗?

2 个答案:

答案 0 :(得分:2)

如果您要模拟类中的方法(看起来像您正在做的那样),建议您使用jest.spyOn。很简单,您可以将返回值模拟为每次测试所需的值。

ffmpeg -i 1.mp4 -i logo.png -i picture.png -filter_complex "[0:v][1:v]overlay=main_w-overlay_w-20:20[bg];[bg][2:v]overlay=10:10[v]" -map "[v]" -map 0:a -c:a copy output.mp4

答案 1 :(得分:1)

更新

由于这两种方法都可以工作,并且它们可能有用,因此我将在这里留下答案。

...但是对于这种特殊情况,@ Daniel是正确的,模拟原型方法最简单


一种简单的处理方法是将myService.js模拟为单例...

...然后,您可以获取doOtherStuff的模拟功能并根据每次测试进行更改:

const myClass = require(`../index`);

jest.mock(`../myService`, () => {
  const doOtherStuff = jest.fn();  // <= create a mock function for doOtherStuff
  const result = { doOtherStuff };
  return function() { return result; };  // <= always return the same object
});
const doOtherStuff = require('./myService')().doOtherStuff;  // <= get doOtherStuff

describe(`service-tests - index`, () => {

  test(`doStuff and test otherStuff`, async () => {
    doOtherStuff.mockReturnValue(1);  // <= mock it to return something
    const result = await myClass.doStuff((err, data) => data);
    expect(result).toBe(1);  // Success!
  });

  test(`doStuff and test otherStuff`, async () => {
    doOtherStuff.mockReturnValue('something else');  // <= mock it to return something else
    const result = await myClass.doStuff((err, data) => data);
    expect(result).toBe('something else');  // Success!
  });
});

它还可以自动模拟myService.js并使用mockImplementation ...

...但是由于index.js在运行后立即创建了一个myService实例 ,因此您必须确保在之前您需要index.js

jest.mock(`../myService`);  // <= auto-mock
const myService = require('../myService');
const doOtherStuff = jest.fn();
myService.mockImplementation(function() { return { doOtherStuff }; });

const myClass = require(`../index`);  // <= now require index

describe(`service-tests - index`, () => {

  test(`doStuff and test otherStuff`, async () => {
    doOtherStuff.mockReturnValue(1);  // <= mock it to return something
    const result = await myClass.doStuff((err, data) => data);
    expect(result).toBe(1);  // Success!
  });

  test(`doStuff and test otherStuff`, async () => {
    doOtherStuff.mockReturnValue('something else');  // <= mock it to return something else
    const result = await myClass.doStuff((err, data) => data);
    expect(result).toBe('something else');  // Success!
  });
});