Javascript 如何在Jest中重置测试之间模拟调用的录制?

Javascript 如何在Jest中重置测试之间模拟调用的录制?,javascript,jestjs,Javascript,Jestjs,我正在学习Jest和现代JavaScript,并尝试测试一段代码。我的测试分组在一个descripe()容器中,我想在测试之间重置模拟(和模拟计数)。在处理重置或清除模拟数据的堆栈溢出方面似乎存在一些问题,但在我的情况下,这些问题似乎不起作用,而且我对JS来说太陌生,无法理解其中的区别 这是我的SUT(在source.js): module.exports=异步函数(延迟){ 让查询; 让我们确定; for(设i=0;isetTimeout(resolve,ms)); } }; 以下是测试:

我正在学习Jest和现代JavaScript,并尝试测试一段代码。我的测试分组在一个
descripe()
容器中,我想在测试之间重置模拟(和模拟计数)。在处理重置或清除模拟数据的堆栈溢出方面似乎存在一些问题,但在我的情况下,这些问题似乎不起作用,而且我对JS来说太陌生,无法理解其中的区别

这是我的SUT(在
source.js
):

module.exports=异步函数(延迟){
让查询;
让我们确定;
for(设i=0;i<5;i++){
query=context.functions.execute('getNextQuery');
如果(查询){
ok=context.functions.execute('runQuery',query);
如果(确定){
execute('markQueryAsRun',query.id);
}
}否则{
打破
}
//善待API
等待睡眠(延迟);
}
功能睡眠(ms){
返回新承诺(resolve=>setTimeout(resolve,ms));
}
};
以下是测试:

const findandrunquerys=require('./source');
description('FindRunQueries'的一些测试,()=>{
设globalMocks={};
//context.functions.execute()变为模拟
global.context={
职能:{
执行:jest.fn((funcName,…params)=>{
//这将调用我们在每个测试中设置的模拟
返回globalMocks[funcName](…参数);
})
}
};
test('不需要运行查询',async()=>{
//如果这个函数是假的,则不需要模仿其他函数
setGlobalMock('getNextQuery',()=>{
返回null;
});
等待FindRunQueries(0);
//确保仅调用getNextQuery
expect(getNthMockFunctionCall(0)[0]).toBe('getNextQuery');
expect(countMockFunctionCalls()).toBe(1);
});
test('需要运行一个查询',async()=>{
让callCount=0;
//第一次运行时返回对象,第二次运行时返回null
setGlobalMock('getNextQuery',()=>{
if(callCount++==0){
返回{
“修理我”
};
}否则{
返回null;
}
});
setGlobalMock('runQuery',(query)=>{
返回true;
});
setGlobalMock('markQueryAsRun',(queryId)=>{
//不需要归还任何东西
});
等待FindRunQueries(0);
//确保调用了每个func
expect(getNthMockFunctionCall(0)[0]).toBe('getNextQuery');
expect(getNthMockFunctionCall(1)[0]).toBe('runQuery');
expect(getNthMockFunctionCall(2)[0]).toBe('markQueryAsRun');
//这里有第四个调用,它返回null以提前终止循环
expect(getNthMockFunctionCall(3)[0]).toBe('getNextQuery');
//确保没有额外的电话
expect(countMockFunctionCalls()).toBe(4);
});
函数setGlobalMock(funcName,func){
globalMocks[funcName]=func;
}
函数getNthMockFunctionCall(n){
返回global.context.functions.execute.mock.calls[n];
}
函数countMockFunctionCalls(){
返回global.context.functions.execute.mock.calls.length;
}
});
这里有两个测试,
不需要运行任何查询
需要运行一个查询
。错误在第二个测试中,我怀疑正在发生的是模拟录制从第一个测试中持续出现,并破坏了结果

我已通过自行运行此测试确认了这一点:

node node_modules/jest/bin/jest.js -t 'One query needs to be run'
但是,如果我同时运行两个测试,如下所示:

node node_modules/jest/bin/jest.js functions/findAndRunQueries
然后我失败了:

  ● Some tests for findAndRunQueries › One query needs to be run

    expect(received).toBe(expected) // Object.is equality

    Expected: "runQuery"
    Received: "getNextQuery"

      53 |         // Ensure each func is called
      54 |         expect(getNthMockFunctionCall(0)[0]).toBe('getNextQuery');
    > 55 |         expect(getNthMockFunctionCall(1)[0]).toBe('runQuery');
         |                                              ^
      56 |         expect(getNthMockFunctionCall(2)[0]).toBe('markQueryAsRun');
      57 | 
      58 |         // We have a 4th call here, which returns null to terminate the loop early

      at Object.test (functions/findAndRunQueries/findAndRunQueries.test.js:55:46)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 passed, 2 total
Snapshots:   0 total
Time:        0.637s, estimated 1s
Ran all test suites matching /functions\/findAndRunQueries/i.
它表示在第二个测试(
getNthMockFunctionCall(1)[0]
)的第二个调用中的第一个参数是
getNextQuery
,而我期望
runQuery
。我认为这表明第一次测试的模拟结果是持久的

我尝试添加以下内容:

beforeAll(()=>{
开玩笑。clearAllMocks();
});
我相信用玩笑的说法“清除”和“重置”是不同的——清除只是重置计数,重置也会移除模拟实现。所以我想要的是清晰的,但不幸的是这没有什么区别

我还可以尝试什么呢?

您可以尝试添加:

每次(()=>{ 开玩笑的,恢复性的 });
此外,最好在每次测试之前使用
来定义重用的测试变量/模拟,以便为每次测试分别定义它们

之前->每次之前?@jonrsharpe:你说得对-谢谢。就在最后几分钟,我看了看之前的
,想知道:“每个测试都会运行吗?”
:=)
谢谢!我来自PHPUnit背景,在那里我倾向于在之前清理,而不是在之后清理,尽管我认为无论使用何种语言,最佳实践都是备受争议的。我将把这个标记为答案,因为解决方案是将我的“所有”函数更改为“每个”函数,您在这里已经完成了。是的,我想这是一个值得讨论的问题。谢谢你的编辑。在我的手机上输入答案要困难得多!我将查看是否可以更改代码,以便在每个
之前的
中模拟
global.context.functions.execute
。我想我试过了,我想这是徒劳的,但我会再试一次。如您所见,此模拟基于第一个参数-
context.functions调用
globalMocks
对象中的函数。execute
是Mongo Stitch中的一个函数,我正在尝试模拟它,以避免需要进行现场测试。(我怀疑Stitch还处于起步阶段,因此如何编写经过良好测试的应用程序的示例目前可能还不多。我不知道有任何示例,但也许我应该