![](/img/trans.png)
[英]jest.mock(): How to mock ES6 class default import using factory parameter
[英]How to mock es6 class using Jest
我試圖用jest模擬一個Mailer
類,我無法弄清楚如何去做。 文檔沒有提供很多關於它如何工作的例子。 過程是我將觸發一個節點事件password-reset
,當該事件被觸發時,我想使用Mailer.send(to, subject, body)
發送電子郵件。 這是我的目錄結構:
project_root
-- __test__
---- server
------ services
-------- emails
---------- mailer.test.js
-- server
---- services
------ emails
-------- mailer.js
-------- __mocks__
---------- mailer.js
這是我的模擬文件__mocks__/mailer.js
:
const Mailer = jest.genMockFromModule('Mailer');
function send(to, subject, body) {
return { to, subject, body };
}
module.exports = Mailer;
和我的mailer.test.js
const EventEmitter = require('events');
const Mailer = jest.mock('../../../../server/services/emails/mailer');
test('sends an email when the password-reset event is fired', () => {
const send = Mailer.send();
const event = new EventEmitter();
event.emit('password-reset');
expect(send).toHaveBeenCalled();
});
最后我的mailer.js
類:
class Mailer {
constructor() {
this.mailgun = require('mailgun-js')({
apiKey: process.env.MAILGUN_API_KEY,
domain: process.env.MAILGUN_DOMAIN,
});
}
send(to, subject, body) {
return new Promise((reject, resolve) => {
this.mailgun.messages().send({
from: 'Securely App <friendly-robot@securelyapp.com>',
to,
subject: subject,
html: body,
}, (error, body) => {
if (error) {
return reject(error);
}
return resolve('The email was sent successfully!');
});
});
}
}
module.exports = new Mailer();
那么,如何使用Jest成功模擬和測試這個類呢? 非常感謝您的幫助!
您不必模擬郵件程序類,而是mailgun-js
模塊。 所以mailgun是一個函數,它返回返回函數send
的函數messages
。 所以模擬看起來像這樣。
為了快樂的道路
const happyPath = () => ({
messages: () => ({
send: (args, callback) => callback()
})
})
對於錯誤情況
const errorCase = () => ({
messages: () => ({
send: (args, callback) => callback('someError')
})
})
因為你有這2個案例,所以在你的測試中模擬模塊是有意義的。 首先,您必須使用一個簡單的間諜來模擬它,我們稍后可以為我們的案例設置實現,然后我們必須導入模塊。
jest.mock('mailgun-js', jest.fn())
import mailgun from 'mailgun-js'
import Mailer from '../../../../server/services/emails/mailer'
由於您的模塊使用promises,我們有2個選項要么從測試中返回promise,要么使用async/await
。 我使用后面的更多信息看看這里 。
test('test the happy path', async() => {
//mock the mailgun so it returns our happy path mock
mailgun.mockImplementation(() => happyPath)
//we need to use async/awit here to let jest recognize the promise
const send = await Mailer.send();
expect(send).toBe('The email was sent successfully!')
});
如果你想測試使用正確的參數調用mailgun send
方法,你需要調整mock如下:
const send = jest.fn((args, callback) => callback())
const happyPath = () => ({
messages: () => ({
send: send
})
})
現在您可以檢查發送的第一個參數是否正確:
expect(send.mock.calls[0][0]).toMatchSnapshot()
僅供Google員工和未來的訪問者使用,以下是我為ES6課程設置開玩笑的方法。 我在github上也有一個工作示例 ,使用babel-jest來轉換ES模塊語法,以便jest可以正確地模擬它們。
__mocks __ / MockedClass.js
const stub = {
someMethod: jest.fn(),
someAttribute: true
}
module.exports = () => stub;
您的代碼可以使用new調用它,在測試中,您可以調用該函數並覆蓋任何默認實現。
example.spec.js
const mockedClass = require("path/to/MockedClass")();
const AnotherClass = require("path/to/AnotherClass");
let anotherClass;
jest.mock("path/to/MockedClass");
describe("AnotherClass", () => {
beforeEach(() => {
mockedClass.someMethod.mockImplementation(() => {
return { "foo": "bar" };
});
anotherClass = new AnotherClass();
});
describe("on init", () => {
beforeEach(() => {
anotherClass.init();
});
it("uses a mock", () => {
expect(mockedClass.someMethod.toHaveBeenCalled();
expect(anotherClass.settings)
.toEqual(expect.objectContaining({ "foo": "bar" }));
});
});
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.