1. ホーム
  2. javascript

[解決済み】Jestを使用してes6クラスをモックする方法

2022-02-14 14:19:54

質問

あるクラスをモック化しようとしています。 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 <[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を使って、このクラスをうまくモックし、テストするにはどうしたらいいでしょうか?助けてくれてありがとうございます。

どのように解決するのですか?

メーラークラスのモックを作成する必要はありませんが mailgun-js モジュールを使用します。つまりmailgunは、関数 messages を返す関数 send . ということで、モックはこんな感じになります。

ハッピーパスの場合

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'

あなたのモジュールはプロミスを使用しているので、テストからプロミスを返すか、あるいは 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!')
});

をテストしたい場合は、メールガンの send メソッドが正しいパラメータで呼び出されるようにするには、このようなモックを作成する必要があります。

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

これで、sendの最初のパラメータが正しいかどうか確認できました。

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