2017-05-03 2 views
8

jest를 사용하여 Mailer 클래스를 모의하려고하는데 어떻게해야하는지 알 수 없습니다. 문서는 이것이 어떻게 작동하는지에 대한 많은 예를 제공하지 않습니다. 그 과정은 내가 노드 이벤트 password-reset을 해고하고 해당 이벤트가 시작되면 Mailer.send(to, subject, body)을 사용하여 이메일을 보내려고합니다.Jest를 사용하여 es6 클래스를 조롱하는 방법

다음
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 <[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(); 

Jest를 사용하여이 클래스를 모의하고 테스트하려면 어떻게해야합니까? 도와 주셔서 대단히 감사합니다!

답변

13

메일러 클래스를 모방하지 않고 mailgun-js 모듈을 모의 할 필요가 없습니다. 따라서 mailgun은 send 함수를 반환하는 함수 messages을 반환하는 함수입니다. 그러니 그 모의 동물은 이렇게 보일 것입니다. 오류의 경우

const errorCase =() => ({ 
    messages:() => ({ 
    send: (args, callback) => callback('someError') 
    }) 
}) 

의 행복 경로

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을 사용 중 하나를 사용합니다. 나중에 자세한 정보를 보려면 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 직원과 향후 방문자에게 ESX 클래스의 jest mocking 설정 방법은 다음과 같습니다. 도 있습니다. jest가 올바르게 조롱 할 수 있도록 ES 모듈 구문을 투명하게 표시하는 바벨 퀘스트가 있습니다.

__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입니다. 나는 그것이 "path/to/MockedClass"가되어야한다고 생각합니다. 그렇습니까? –

+1

@ PacketTracer 당신이 맞습니다! 코드 예제를 업데이트했습니다. –