【发布时间】:2016-09-17 04:02:39
【问题描述】:
我想监视作为命名导出导出的子函数,但是,我们似乎无法监视它。
假设我在operations.js 中有两个名为add 和multiply 的函数,并将它们导出为命名导出:
const add = (a, b) => {
return a + b
}
const multiply = (a, b) => {
let result = 0
for (let i = 0; i < b; i++) {
result = add(a, result)
}
return result
}
export { add, multiply }
而测试文件使用sinon-chai来试图窥探add函数:
import chai, { expect } from 'chai'
import sinon from 'sinon'
import sinonChai from 'sinon-chai'
import * as operations from './operations'
chai.use(sinonChai)
describe('multiply', () => {
it('should call add correctly', () => {
sinon.spy(operations, 'add')
operations.multiply(10, 5)
expect(operations.add).to.have.been.callCount(5)
operations.add.restore()
})
})
结果是
AssertionError: expected add to have been called exactly 5 times, but it was called 0 times
但是,如果我像下面这样直接调用operations.add,它通过了测试:
describe('multiply', () => {
it('should call add correctly', () => {
sinon.spy(operations, 'add')
operations.add(0, 5)
operations.add(0, 5)
operations.add(0, 5)
operations.add(0, 5)
operations.add(0, 5)
expect(operations.add).to.have.been.callCount(5)
operations.add.restore()
})
})
似乎 sinon-spy 为 operations.add 创建了一个新引用,但 multiply 函数仍然使用已绑定的旧引用。
如果这些函数被命名为exports,那么窥探add函数的add函数的正确方法是什么?
一般来说,如何监视一个被测试的父函数的子函数,它们都被命名为exports?
[更新]
multiply 函数只是一个例子。我的主要观点是测试父函数是否调用子函数。但是,我不希望该测试依赖于子功能的实现。所以,我只想窥探子函数是否被调用。你可以想象multiply 函数是registerMember 函数,add 函数是sendEmail 函数。 (这两个函数都被命名为导出。)
【问题讨论】:
-
从经验来看,像这样的测试最终会变得非常脆弱。
multiply的返回值是重要的,而不是它是如何实现的。最好专注于测试。 -
export { add, multiply }类似于export { add : add, multiply : multiply }。所以导出的对象包含对原始方法的引用,sinon.spy()替换了引用而不是原始方法(这是multiply()使用的)。 -
@loganfsmyth 在某些情况下,一个函数不返回任何值,但它会调用其他函数来做某事。因此,我们想测试它是否调用了其他函数。
-
@robertklep 我想是的。所以,我想知道是否可以监视它。 (不一定是sinon。)
-
@Supasate 我不认为你可以监视它,因为
multiply()没有使用导出的引用。
标签: javascript unit-testing ecmascript-6 spy sinon-chai