【问题标题】:How to expect one function to call another function?如何期望一个函数调用另一个函数?
【发布时间】:2017-04-07 21:06:00
【问题描述】:

我正在尝试模拟一个函数调用,并希望它在其中调用另一个函数一次。

myFunctions.test.js

import { resetModal } from '../myFunctions.js';

describe('resetModal', () => {
  it('calls the clearSomethingInModal function', () => {
    const clearSomethingInModal = jest.fn();
    resetModal();
    expect(clearSomethingInModal.mock.calls.length).toBe(1);
  })
})

myFunctions.js

export resetModal() {
  clearSomethingInModal()
}

但是,Jest 输出显示它尚未被调用。我怎样才能最好地做到这一点?

【问题讨论】:

标签: javascript unit-testing jestjs


【解决方案1】:

您的方法不起作用,因为您仅在测试文件的上下文中模拟clearSomethingInModal,因此myFunctions.js 中的clearSomethingInModal 仍然是原始的。要点是你不能模拟直接在myFunctions.js 中创建的东西。您唯一可以模拟的是:

  1. 您导入到myFunctions.js 的模块,例如import clearSomethingInModal from 'clearSomethingInModal'
  2. 从测试中调用函数时传递给函数的回调;

如果您将myFunctions.js 视为一个黑盒,您可以在其中控制输入内容(如导入或函数参数)以及测试输出内容,这是有道理的。但是你不能测试盒子里发生的事情。

以下是反映列表中 2 点的两个示例:

myFunctions.test.js

import { resetModal } from '../myFunctions.js';
import clearSomethingInModal from 'clearSomethingInModal';

jest.mock('clearSomethingInModal', () => jest.fn())

describe('resetModal', () => {
  it('calls the clearSomethingInModal function', () => {
    resetCreationModal();
    expect(clearSomethingInModal.mock.calls.length).toBe(1);
  })
})

myFunctions.js

import clearSomethingInModal from 'clearSomethingInModal';

export resetModal() {
  clearSomethingInModal()
}

myFunctions.test.js

import { resetModal } from '../myFunctions.js';

describe('resetModal', () => {
  it('calls the clearSomethingInModal function', () => {
    const clearSomethingInModal = jest.fn();
    resetCreationModal(clearSomethingInModal);
    expect(clearSomethingInModal.mock.calls.length).toBe(1);
  })
})

myFunctions.js

export resetModal(clearSomethingInModal) {
  clearSomethingInModal()
}

【讨论】:

  • 谢谢安德烈亚斯,这是一个很好的解释。所以我认为在不改变我的函数结构的情况下,我无法以我想要的方式进行测试。那么,(a)这是否意味着函数设计中存在问题,以及(b)在当前形式下,是否有任何有效的测试可以应用于它?请注意,“resetModal”函数还调用其中的许多其他函数,为简洁起见我省略了
  • 但是我们不能只插入一个 spy 函数来模拟内部函数吗?
【解决方案2】:

另一种方法是使用done 并模拟或监视最后一个函数的实现,并检查之前的函数是否被调用。

it('should call function2 after function1', (done) => {
    expect.assertions(2)

    function2.mockImplementationOnce(() => {
      expect(function1).toHaveBeenCalled()
      done()
    })

    act() // This is where you run function you are testing
  })

这个解决方案的缺点是测试的结构不是

// arrange
// act
// assert

而是

// arrange & assert
// act

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-02
    • 2018-12-02
    • 2011-05-30
    • 2020-11-17
    • 1970-01-01
    • 1970-01-01
    • 2021-07-03
    相关资源
    最近更新 更多