4

我想监视作为命名导出导出的子函数,但是,我们似乎无法监视它。

假设我有两个函数调用addmultiplyinoperations.js并将它们导出为命名导出:

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函数仍然使用已经绑定的旧引用。

如果这些函数被命名为导出,那么监视add这个函数的函数的正确方法是什么?multiply

一般来说,如何监视一个被测试的父函数的子函数,它们都被命名为导出?

[更新]

multiply函数只是一个例子。我的主要观点是测试父函数是否调用子函数。但是,我不希望该测试依赖于子功能的实现。所以,我只想窥探子函数是否被调用。你可以想象multiply函数是registerMember函数,add函数是sendEmail函数。(这两个函数都被命名为导出。)

4

1 回答 1

-2

对于我自己的问题,我有一个解决方法。

目前,multiply()功能与功能紧密耦合add()。这使得测试变得困难,尤其是当导出的函数获得新的引用时。

因此,要监视子函数调用,我们可以将子函数传递给父函数。是的,它是dependency injection

因此,在 中operations.js,我们将注入addFnmultiply()使用它,如下所示:

const add = (a, b) => {
  return a + b
}

const multiply = (a, b, addFn) => {
  let result = 0

  for (let i = 0; i < b; i++) {
    result = addFn(a, result)
  }
  return result
}

export { add, multiply }

然后,在测试中,我们可以add()像这样监视函数:

describe('multiply', () => {
  it('should call add correctly', () => {
      sinon.spy(operations, 'add')

      operations.multiply(10, 5, operations.add)
      expect(operations.add).to.have.been.callCount(5)

      operations.add.restore()
  })
})

现在,它的作用是测试子函数是否被正确调用。

(注意:缺点是我们需要改变multiply()功能)

于 2016-05-20T14:06:37.490 回答