用Jest嘲笑课程

问题描述 投票:1回答:2

鉴于我有一个类调用函数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

有没有人曾经这样做过?

class ecmascript-6 mocking jestjs
2个回答
2
投票

如果你想模拟一个类中的方法,它看起来像你正在做的,我建议你使用jest.spyOn。它很简单,您可以将返回值模拟为每次测试所需的任何值。

const myClass = require('../index');
const myService = require('../myService');

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

  let doOtherStuffMock;
  beforeAll(() => {
    doOtherStuffMock = jest.spyOn(myService.prototype, 'doOtherStuff');
  });

  it('mocks doOtherStuff one way', async () => {
    doOtherStuffMock.mockResolvedValue('I am a mocked value');
    const result = await myClass.doStuff((err, data) => data);
    expect(result).toBe("I am a mocked value");
  });

  it('mocks doOtherStuff another way', async () => {
    doOtherStuffMock.mockResolvedValue('I am DIFFERENT mocked value');
    const result = await myClass.doStuff((err, data) => data);
    expect(result).toBe('I am DIFFERENT mocked value');
  });
});

1
投票

更新

我将在这里留下这个答案,因为这两种方法都有用,它们可以有用......

...但对于这个特殊情况,@丹尼尔是对的,嘲笑原型方法是最简单的


一个简单的方法来处理这个是模拟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!
  });
});
© www.soinside.com 2019 - 2024. All rights reserved.