繁体   English   中英

如何在Node.js中模拟所需文件?

[英]How to mock required files in Node.js?

我正在尝试模拟节点模块,以便它将返回模拟数据。 但是在我的测试中,它仍在进行实际调用。 考虑以下代码:

const makeRequestStructure = require('./modules/makeRequestStructure.js').makeRequestStructure
const normalizeFinalResponse = require('./modules/normalizeFinalResponse.js').normalizeFinalResponse
const doARequest = require('./modules/doARequest.js').doARequest

exports.addPost = (event) => {
  const requestStructure = makeRequestStructure('POST', '/posts')

  const requestPostData = {
    title: event.body.title,
    content: event.body.content
  }

  return doARequest(requestStructure, requestPostData).then((res) => {
    const finalResponse = normalizeFinalResponse(200, res)
    return finalResponse
  }).catch((err) => {
    const finalResponse = normalizeFinalResponse(400, err)
    return finalResponse
  })
}

我有以下测试文件:

const mock = require('mock-require')
const sinon = require('sinon')
const expect = require('chai').expect

const addPost = require('../addPost.js')

describe('the addPost API call', () => {
  beforeEach(() => {
    mock('../modules/doARequest', { doARequest: function() {
      return Promise.resolve({})
    }})
  });
  it('Returns with a statusCode of 200', () => {
    const event = { body: { title: 'Lorem ipsum', content: 'Lorem ipsum dolor sit amet' } }
    const expectedReturn = { id: 20000000000000 }
    return addPost.addPost(event).then((res) => {
      expect(res.body.message).to.eql(expectedReturn)
    })
  });
})

该测试正在对https://jsonplaceholder.typicode.com/posts进行实际调用,并返回{ id: 101 } 但是我希望它返回{ id: 20000000000000 } 我试图使用Nock模拟请求。 但是,主机名是在.env文件中定义的,并且可能会有所不同,具体取决于运行脚本的服务器。

doARequest.js文件如下所示:

const https = require('https')

module.exports.doARequest = function (params, postData) {
  return new Promise((resolve, reject) => {
    const req = https.request(params, (res) => {
      let body = []
      res.on('data', (chunk) => {
        body.push(chunk)
      })
      res.on('end', () => {
        try {
          body = JSON.parse(Buffer.concat(body).toString())
        } catch (e) {
          reject(e)
        }
        resolve(body)
      })
    })
    req.on('error', (err) => {
      reject(err)
    })
    if (postData) {
      req.write(JSON.stringify(postData))
    }
    req.end()
  })
}

我在这里做错了什么? 任何帮助将不胜感激。

CommonJS模块产生单例导出对象。 导入模块后,将不对其进行评估。 mock(...)不会产生任何影响,因为在导入addPost时已对原始的doARequest模块进行了评估。

mock-require 提供了一种重新评估模块的方法 addPost不应导入测试文件的顶部。 相反,应该将其导入使用它的测试中:

const addPost = mock.reRequire('../addPost.js');

作为使用reRequire模块的替代estus解决方案,您可以使用“依赖注入”。

问题是,你直接取决于doARequest.js在-module addPost.js ,从而使其难以讥笑它的行为。 这是依赖注入派上用场的地方,因为您只需在单元测试中传递一个模拟的doARequest-module即可:

// addPost.js
exports.addPost = (event, doARequest) => {
    const requestStructure = makeRequestStructure('POST', '/posts')

    const requestPostData = {
        title: event.body.title,
        content: event.body.content
    }

    return doARequest(requestStructure, requestPostData).then((res) => {
        const finalResponse = normalizeFinalResponse(200, res)
        return finalResponse
    }).catch((err) => {
        const finalResponse = normalizeFinalResponse(400, err)
        return finalResponse
    })
}

// addPost.test.js
describe('the addPost API call', () => {        
    it('Returns with a statusCode of 200', () => {
        const mockedDoARequest = () => Promise.resolve({ "whateverResponseYouLike": "12345" });
        const event = { body: { title: 'Lorem ipsum', content: 'Lorem ipsum dolor sit amet' } }
        const expectedReturn = { id: 20000000000000 }
        return addPost.addPost(event, mockedDoARequest).then((res) => {
            expect(res.body.message).to.eql(expectedReturn)
        })
    });
})

您将在其他任何地方传递真实模块,即

const doARequest = require('./modules/doARequest.js').doARequest
...
return addPost.addPost(event, doARequest).then(...)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM