2

I'm trying to use Jest for mock and spy a node_modules library, but I need support:

this is the code to test

const mailgun = require('mailgun-js')

const mg = mailgun({
  apiKey: process.env.MAIL_GUN_API_KEY,
  domain: process.env.MAIL_GUN_DOMAIN,
  host: process.env.MAIL_GUN_HOST
})

module.exports = (data) => mg.messages().send(data)

now testing it

__mock__/mailgun-js.js
const mailgun = require('mailgun-js')
jest.genMockFromModule('mailgun-js')
module.exports = mailgun
tests/test.js
const mailgun = require('mailgun-js')

jest.mock('mailgun-js', () => {
  return jest.fn(() => ({
    messages: () => ({
      send: jest.fn(() => Promise.resolve())
    })
  }))
})

expect(mailgun).toHaveBeenCalledTimes(1)
expect(mailgun).toHaveBeenCalledWith({
  apiKey: process.env.MAIL_GUN_API_KEY,
  domain: process.env.MAIL_GUN_DOMAIN,
  host: process.env.MAIL_GUN_HOST
})

Right now toHaveBeenCalledTimes and toHaveBeenCalledWith works, but I would also check the argument passed to .send (data)

Manu
  • 23
  • 1
  • 3

1 Answers1

4

You can spy on the send function in your mock then verify that itHaveBeenCalled when you run add(data)

Like this:

const mailgun = require('mailgun-js')
const mockSend = jest.fn(() => Promise.resolve());

jest.mock('mailgun-js', () => {
  return jest.fn(() => ({
    messages: () => ({
      send: mockSend
    })
  }))
})

test('test', () => {
  const add = require('./add');
  expect(mailgun).toHaveBeenCalledTimes(1)
  expect(mailgun).toHaveBeenCalledWith({
    apiKey: process.env.MAIL_GUN_API_KEY,
    domain: process.env.MAIL_GUN_DOMAIN,
    host: process.env.MAIL_GUN_HOST
  });

  const data = {foo: 'bar'};
  add(data);
  expect(mockSend).toHaveBeenCalledWith(data);
});

Pay attention - if you'll change the mockSend name to a name without prefix mock, you'll get an error:

The module factory of jest.mock() is not allowed to reference any out-of-scope variables.

Mosh Feu
  • 28,354
  • 16
  • 88
  • 135