2017-05-03 7 views
8

jestを使ってクラスMailerを模擬しようとしていますが、その方法を理解できません。ドキュメントでは、これがどのように動作するかの例はあまりありません。このプロセスはノードのイベントpassword-resetが発生し、そのイベントが発生したときにMailer.send(to, subject, body)を使用して電子メールを送信したいと考えています。ここに私のディレクトリ構造は次のとおりです。Jestを使ってes6クラスを模擬する方法

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 <[email protected]>', 
     to, 
     subject: subject, 
     html: body, 
     }, (error, body) => { 
     if (error) { 
      return reject(error); 
     } 

     return resolve('The email was sent successfully!'); 
     }); 
    }); 
    } 

} 

module.exports = new Mailer(); 
ここ

project_root 
-- __test__ 
---- server 
------ services 
-------- emails 
---------- mailer.test.js 
-- server 
---- services 
------ emails 
-------- mailer.js 
-------- __mocks__ 
---------- mailer.js 

は私のモックファイル__mocks__/mailer.jsです

Jestを使って、このクラスを模擬してテストするにはどうすればいいですか?助けてくれてありがとう!

答えて

13

メーラークラスではなく、mailgun-jsモジュールをモックする必要はありません。したがって、mailgunは、send関数を返す関数messagesを返す関数です。だから模擬はこのように見えるでしょう。エラーの場合の幸せなパス

const happyPath =() => ({ 
    messages:() => ({ 
    send: (args, callback) => callback() 
    }) 
}) 

ため

​​

あなたはこの2例を持っているとして、それはあなたのテスト内のモジュールを模擬するために意味をなします。まず、単純なスパイでモックする必要があります。ここで、後で実装を設定し、モジュールをインポートする必要があります。

jest.mock('mailgun-js', jest.fn()) 
import mailgun from 'mailgun-js' 
import Mailer from '../../../../server/services/emails/mailer' 

あなたのモジュールは、我々は2つのオプションを持っているいずれかの試験または使用async/awaitから約束を返す約束を使用するので。私はより多くの情報のための後の1つを見てくださいhereを使用します。

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方法は、あなたがこのようなモックを適応する必要があり、正しいパラメータで呼び出されたことをテストしたい場合:今、あなたは、送信のための最初のパラメータかどうかを確認でき

const send = jest.fn((args, callback) => callback()) 
const happyPath =() => ({ 
    messages:() => ({ 
    send: send 
    }) 
}) 

正しかった:

expect(send.mock.calls[0][0]).toMatchSnapshot() 
+0

私は家に帰って試してみることができません。非常に素晴らしい説明をいただきありがとうございます。 – dericcain

3

Google社員と将来の訪問者のために、ここではES6クラス用のjest mockingを設定しました。 私はworking example at githubも持っていて、jestが適切にモックできるように、ESモジュールの構文を透明化するためのbabel-jestを持っています。

__mocks __/MockedClass.js

const stub = { 
    someMethod: jest.fn(), 
    someAttribute: true 
} 

module.exports =() => stub; 

あなたのコードは、新しいでこれを呼び出すことができますし、あなたのテストで、あなたは、関数を呼び出し、任意のデフォルトの実装を上書きすることができます。

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" })); 
    }); 
    }); 

}); 
+0

私のために働いていません。 'mockedClass.someMethod'は' undefined'です。 jestの使用21.2.1。 – stone

+0

"path/to/YourClass"とは何ですか?コードに表示されるクローンは、mockedClassとAnotherClassだけです。私はそれが "パス/ to/MockedClass"でなければならないと思います。 –

+1

@PacketTracerあなたは正しいです!コード例を更新しました。 –

関連する問題