Javascript 异步函数中的意外调用时间

Javascript 异步函数中的意外调用时间,javascript,reactjs,testing,sinon,Javascript,Reactjs,Testing,Sinon,我正在使用sinon的react应用程序进行测试,以下是一些背景 为用户创建一个文件上传器,用于将文件上传到服务器,上传完成后,将弹出一个对话框,显示上传文件的详细信息 容器 测试升级.spec.js 测试是检查函数this.updateProgressBar是否正在执行,但是我只在第一次调用中得到被调用的spyed,而不是第二次调用 从控制台日志消息的顺序中,我可以看到catch中的在then中的之前,因此很确定catch块是在测试用例评估函数之前执行的,关于这一点有什么线索吗?多谢各位

我正在使用sinon的react应用程序进行测试,以下是一些背景

  • 为用户创建一个文件上传器,用于将文件上传到服务器,上传完成后,将弹出一个对话框,显示上传文件的详细信息
容器

测试
升级.spec.js

测试是检查函数this.updateProgressBar是否正在执行,但是我只在第一次调用中得到被调用的spyed,而不是第二次调用

从控制台日志消息的顺序中,我可以看到catch中的
在then
中的
之前,因此很确定catch块是在测试用例评估函数之前执行的,关于这一点有什么线索吗?多谢各位

...
const spyUpdateProgressBar = spy(upgradeAppInstance, 'updateProgressBar');

it('should hide the progress bar when upgrade is failed', function (done) {
        fetchMock.post(regUploadExp, mockOkUploadHttpResponse);
        fetchMock.post(regUpgradeExp, mockHttpUpgradeResponse);

        upgradeAppInstance.onFileUpload().then(() => {
            wrapper.update();
            expect(wrapper.find(ADialog).at(0).props().open).to.equal(true);
            const mockButtons2 = wrapper.find(ADialog).dive().at(0).find(Button);
            expect(spyUpdateProgressBar.calledOnce).to.equal(true); // This test is passed as expected
            spyUpdateProgressBar.resetHistory();

            // simulate upgrade process
            mockButtons2.at(1).simulate('click');
            console.log('in then');
        });

        setImmediate(() => {
            console.log(spyUpdateProgressBar.callCount);
            expect(spyUpdateProgressBar.calledOnce).to.equal(true); // failed in this expect, expecting true but get false
            done();
        });
    });

你依靠的是黑客,这会导致错误的行为
setImmediate
-它为什么在那里?坚持承诺。问题没有提到测试框架。是摩卡咖啡吗?您不需要
done
在那里,它支持承诺。catch块在测试用例评估函数之前执行,是否有关于这方面的线索-不清楚submitFn在哪里被调用,但它的承诺没有链接到任何地方,这就是线索
restfulApiCall
应该首先被模拟,而且
setState
也可能被模拟。请提供丢失的零件。出于可测试性的原因,我认为应该将
submitFn
提取到单独的方法中。@estus感谢您的建议,并为含糊不清的内容感到抱歉,我尝试在catch块(在源代码中)以及测试用例中的then块(如代码所示)中打印(使用
console log
),结果表明,顺序是.catch in src run,然后.catch in test case run nextit不清楚调用
submitFn
的位置>yes,这解释了为什么我试图通过
setImmediate
进行“hack”,因为
setState
弹出另一个对话框,用户点击
submitFn
,执行另一个操作(实际升级),因为我无法控制用户何时单击该对话框按钮。您正在执行的是集成/e2e测试。要进行正确的单元测试,submitFn应该提取到单独的方法。它应该在一个测试中存根并在另一个测试中直接调用。这样,它返回的承诺可以正确链接。
...
const spyUpdateProgressBar = spy(upgradeAppInstance, 'updateProgressBar');

it('should hide the progress bar when upgrade is failed', function (done) {
        fetchMock.post(regUploadExp, mockOkUploadHttpResponse);
        fetchMock.post(regUpgradeExp, mockHttpUpgradeResponse);

        upgradeAppInstance.onFileUpload().then(() => {
            wrapper.update();
            expect(wrapper.find(ADialog).at(0).props().open).to.equal(true);
            const mockButtons2 = wrapper.find(ADialog).dive().at(0).find(Button);
            expect(spyUpdateProgressBar.calledOnce).to.equal(true); // This test is passed as expected
            spyUpdateProgressBar.resetHistory();

            // simulate upgrade process
            mockButtons2.at(1).simulate('click');
            console.log('in then');
        });

        setImmediate(() => {
            console.log(spyUpdateProgressBar.callCount);
            expect(spyUpdateProgressBar.calledOnce).to.equal(true); // failed in this expect, expecting true but get false
            done();
        });
    });