鉴于我有一个类调用函数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
有没有人曾经这样做过?
如果你想模拟一个类中的方法,它看起来像你正在做的,我建议你使用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');
});
});
更新
我将在这里留下这个答案,因为这两种方法都有用,它们可以有用......
...但对于这个特殊情况,@丹尼尔是对的,嘲笑原型方法是最简单的
一个简单的方法来处理这个是模拟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!
});
});