[英]Mocking classes with Jest
鑒於我有一個類調用函數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!
});
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.