如何使用Jest测试javascript中的抽象函数?

时间:2018-10-25 23:38:56

标签: javascript unit-testing jestjs

我有2个如下定义的javascript A和B函数,并且通过另一个API公开,如下所示,我想测试函数A是否在调用B。

function A () {
  B()
}

function B () {
  console.log('B is called')
}

export function API (){
  return {
    a: A,
    b: B
  }
}

我尝试测试功能的方式如下所示,

import { API } from './actions-beta'

describe('test A', () => {
  test('', () => {
    const fn = API()
    console.log(fn)
    const spy = jest.spyOn(fn, 'b')
    fn.a()
    expect(spy).toHaveBeenCalled()
  })
})

1 个答案:

答案 0 :(得分:1)

无法测试是否以编写代码的方式调用B

详细信息

jest.spyOn replaces the function property on the object with a spy

jest.spyOn(fn, 'b')将用间谍替换对象b的{​​{1}}属性。

fn会调用fn.a(),后者会直接调用A,它不会调用B,因此间谍不会被调用。

解决方案

fn.b需要使用一个对象属性来调用A ,该对象属性可以在测试期间替换为间谍

创建间谍时,对象通常是模块

这就是为什么监视导出函数非常容易而监视非导出函数非常困难的原因,这引出了重要的一点:如果一个函数在同一模块中调用一个非导出函数,则它是只是一个在模块外部不可见的实现细节,并且使用黑盒测试方法就不需要对其进行测试。

如果您发现B不仅仅是实现细节,并且您想监视或存根其功能,那么最简单的方法(尤其是对于此代码,其中export是每次创建新对象的函数被调用)是将B移到其自己的模块中:


actions-beta.js

B

lib.js

import { B } from './lib';

export function A () {
  B()
}

export function API (){
  return {
    a: A,
    b: B
  }
}

测试:

export function B () {
  console.log('B is called')
}