How to unit test a Node.js module that requires other modules and how to mock the global require function?

后端 未结 8 2071
我在风中等你
我在风中等你 2020-11-29 16:38

This is a trivial example that illustrates the crux of my problem:

var innerLib = require(\'./path/to/innerLib\');

function underTest() {
    return innerLi         


        
8条回答
  •  北海茫月
    2020-11-29 17:22

    Simple code to mock modules for the curious

    Notice the parts where you manipulate the require.cache and note require.resolve method as this is the secret sauce.

    class MockModules {  
      constructor() {
        this._resolvedPaths = {} 
      }
      add({ path, mock }) {
        const resolvedPath = require.resolve(path)
        this._resolvedPaths[resolvedPath] = true
        require.cache[resolvedPath] = {
          id: resolvedPath,
          file: resolvedPath,
          loaded: true,
          exports: mock
        }
      }
      clear(path) {
        const resolvedPath = require.resolve(path)
        delete this._resolvedPaths[resolvedPath]
        delete require.cache[resolvedPath]
      }
      clearAll() {
        Object.keys(this._resolvedPaths).forEach(resolvedPath =>
          delete require.cache[resolvedPath]
        )
        this._resolvedPaths = {}
      }
    }
    

    Use like:

    describe('#someModuleUsingTheThing', () => {
      const mockModules = new MockModules()
      beforeAll(() => {
        mockModules.add({
          // use the same require path as you normally would
          path: '../theThing',
          // mock return an object with "theThingMethod"
          mock: {
            theThingMethod: () => true
          }
        })
      })
      afterAll(() => {
        mockModules.clearAll()
      })
      it('should do the thing', async () => {
        const someModuleUsingTheThing = require('./someModuleUsingTheThing')
        expect(someModuleUsingTheThing.theThingMethod()).to.equal(true)
      })
    })
    

    BUT... proxyquire is pretty awesome and you should use that. It keeps your require overrides localized to tests only and I highly recommend it.

提交回复
热议问题