Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mock an external module's function with Jest

Tags:

jestjs

Can Jest's mocking handle functions from modules I didn't write?

node-yelp-api-v3 has Yelp.searchBusiness(String) but my attempts to use Jest's mocking functionality are unsuccessful. The Jest examples seem to assume that I'm mocking a module I have in the project. From the documentation I'm also unclear how to mock a specific function in a module.

Neither of these are working:

jest.mock('Yelp.searchBusiness', () => {
  return jest.fn(() => [{<stubbed_json>}])
})

or

jest.mock('Yelp', () => {
  return jest.fn(() => [{<stubbed_json>}])
})

I'm currently using sinon but would like to use just Jest. This Sinon approach works:

var chai = require('chai')
var should = chai.should()
var agent = require('supertest').agent(require('../../app'))

const Yelp = require('node-yelp-api-v3')

var sinon = require('sinon')
var sandbox

describe('router', function(){
  beforeEach(function(){
    sandbox = sinon.sandbox.create()
    stub = sandbox.stub(Yelp.prototype, 'searchBusiness')
  })

  afterEach(function(){
    sandbox.restore()
  })

  it ('should render index at /', (done) => {
    /* this get invokes Yelp.searchBusiness */
    agent
      .get('/')
      .end(function(err, res) {
        res.status.should.equal(200)
        res.text.should.contain('open_gyro_outline_500.jpeg')

        done()
      })
  })
})
like image 928
eebbesen Avatar asked Aug 10 '17 15:08

eebbesen


Video Answer


1 Answers

Mocking external modules is explained here.

If the module you are mocking is a Node module (e.g.: lodash), the mock should be placed in the __mocks__ directory adjacent to node_modules (unless you configured roots to point to a folder other than the project root) and will be automatically mocked. There's no need to explicitly call jest.mock('module_name').

For your exact case this would mean you need to create a folder __mocks__ with a file node-yelp-api-v3.js in it. In that file you create a mock object from the original module using genMockFromModule and override the method you want to mock.

// __mocks__/node-yelp-api-v3.js

const yelp = jest.genMockFromModule('node-yelp-api-v3')

function searchBusiness() {
    return [{<stubbed_json>}]
}

yelp.searchBusiness = searchBusiness

module.exports = yelp

Additionally you could also wrap the searchBusiness in jest.fn if you want to call assertions like searchBusiness.mock.calls.length for this method later.

like image 133
brass monkey Avatar answered Sep 30 '22 18:09

brass monkey