如何期望一个函数调用另一个函数?
Posted
技术标签:
【中文标题】如何期望一个函数调用另一个函数?【英文标题】: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 输出显示它尚未被调用。我怎样才能最好地做到这一点?
【问题讨论】:
如果resetModal
和clearSomethingInModal
都是从同一个模块导出的,您可以模拟一个并测试另一个。见github.com/facebook/jest/issues/936
【参考方案1】:
您的方法不起作用,因为您仅在测试文件的上下文中模拟clearSomethingInModal
,因此myFunctions.js
中的clearSomethingInModal
仍然是原始的。要点是你不能模拟直接在myFunctions.js
中创建的东西。您唯一可以模拟的是:
-
您导入到
myFunctions.js
的模块,例如import clearSomethingInModal from 'clearSomethingInModal'
;
从测试中调用函数时传递给函数的回调;
如果您将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
【讨论】:
以上是关于如何期望一个函数调用另一个函数?的主要内容,如果未能解决你的问题,请参考以下文章
JMockit 期望 API:如何在方法/构造函数调用时抛出异常