使用testdouble.js对mocha test mock/spy导入库

aif*_*rfa 3 javascript unit-testing node.js

我的模块需要一个外部依赖项:downloadjs导出一个函数而不是Object

import download from 'downloadjs' // download is a function
Run Code Online (Sandbox Code Playgroud)

我的功能

const onExport = () => (dispatch, getState) => {
  let data = getState().get('data')
  let csv = mapDataToCsv(data)

  download(csv, "export-result.csv", "text/csv");
  // dispatch something else
}
Run Code Online (Sandbox Code Playgroud)

单元测试

import download from 'downloadjs'
import td from 'testdouble'

// test case
it('unparse JSON to CSV', () => {
  td.replace('downloadjs') // no this doesn't work

  let store = createStore(reducer, initialState, middleware);
  store.dispatch(target.onExport()); // action calls

  let expected = td.matchers.contains('FOO,SUCCESS')
  // error it calls real download function not mock
  td.verify(download(expected, "export-result.csv", "text/csv")) 
  td.reset()
})
Run Code Online (Sandbox Code Playgroud)

问题

我试图模拟/替换downloadjs以验证它是否使用有效数据进行调用.

既不td.replace(download)也不td.replace('downloadjs')作品

文档说你不应该模拟/替换外部库:

为什么td.replace()不能与外部CommonJS模块一起使用?

那么我该如何测试这段代码呢?

小智 5

您可以围绕第三方库中存在的功能创建包装器(在本例中为downloadjs)并用于td.replace模拟您的包装器.

你的功能

var downloadCSV = require('./downloadCSV.js')

module.exports = () => (dispatch, getState) => {
    downloadCSV('goats')
}
Run Code Online (Sandbox Code Playgroud)

新的包装依赖项

// downloadCSV.js
var download = require('downloadjs')

module.exports = (data) => {
    download(data, 'export-result.csv', 'text/csv')
}
Run Code Online (Sandbox Code Playgroud)

单元测试

describe('csv exporter', () => {
    var subject, downloadCSV
    beforeEach(() => {
        downloadCSV = td.replace('../../lib/downloadCSV.js')
        subject     = require('../../lib/code.js')
    })

    describe('downloading csv', () => {
        it('works', () => {
            subject()()
            td.verify(downloadCSV('goats'))
        })
    });
});
Run Code Online (Sandbox Code Playgroud)

笔记

  1. 请注意双重调用,subject()()因为您有一个函数,它返回您测试的代码中的函数.

  2. 我使用了nodetest double repo中提供的示例文件夹结构来构建这些测试:https://github.com/testdouble/testdouble.js/tree/master/examples/node

  3. 我已经上传了一个包含我的示例代码的存储库供您使用.https://github.com/davemo/td-replace-helper

  4. 我没有包含Redux特定代码,也没有使用ES6样式导入,以避免在示例repo中引入太多依赖项.

  5. 您可能需要按摩您使用ES6样式的导入以便于使用td.replace,请查看此评论主题以获取更多信息:https://github.com/testdouble/testdouble.js/issues/51#issuecomment-207780628