使用sinon进行桩测试时,ava异步测试存在问题

7

我有一些测试需要在一个依赖项的.then.catch块上运行。

import test from 'ava';
import sinon from 'sinon';

// Fake dependency code - this would be imported
const myDependency = {
    someMethod: () => {}
};

// Fake production code - this would be imported
function someCode() {
    return myDependency.someMethod()
        .then((response) => {
            return response;
        })
        .catch((error) => {
            throw error;
        });
}

// Test code

let sandbox;

test.beforeEach(() => {
    sandbox = sinon.sandbox.create();
});

test.afterEach.always(() => {
    sandbox.restore();
});

test('First async test', async (t) => {
    const fakeResponse = {};

    sandbox.stub(myDependency, 'someMethod')
        .returns(Promise.resolve(fakeResponse));

    const response = await someCode();

    t.is(response, fakeResponse);
});

test('Second async test', async (t) => {
    const fakeError = 'my fake error';

    sandbox.stub(myDependency, 'someMethod')
        .returns(Promise.reject(fakeError));

    const returnedError = await t.throws(someCode());

    t.is(returnedError, fakeError);
});

如果你单独运行任意一个测试,测试都会通过。但是如果你同时运行这两个测试,那么测试A的安装会运行,然后在其完成之前,测试B的安装也会运行,导致出现以下错误:
Second async test
   failed with "Attempted to wrap someMethod which is already wrapped"

也许我没有理解如何设置我的测试。是否有一种方法可以强制测试A在开始运行之前完成,然后再运行测试B?
2个回答

15

AVA测试是并发运行的,这会影响你的Sinon存根。

相反,声明你的测试要以串行方式运行,它应该可以正常工作:

test.serial('First async test', ...);
test.serial('Second async test', ...);

14
为了提供更多背景信息,是的,默认情况下测试是并发运行的。这意味着所有测试的beforeEach钩子也会同时运行。正在发生的是beforeEach钩子的每个调用都会替换sandbox变量,因此两个测试实际上使用的是同一个沙盒。您可以通过在beforeEach中分配给t.context来解决这个问题,这样它将在测试中可用。但是两个测试仍然在同时修改相同的依赖项,因此第二个测试仍将无法对该方法进行存根。因此,您需要使用test.serial - Mark Wubben
感谢您的见解,@MarkWubben :) - robertklep

0

串行运行会减慢测试的运行速度。当然,您可以创建单独的变量sandbox1和sandbox2,以防止第一个测试使用在第二个测试中设置的沙盒。但是,为了确保我不犯这个错误,我会在IIFE(立即调用函数表达式)中运行每个测试。一个IIFE中的任何变量都与另一个IIFE中的任何变量不同,即使它们具有相同的名称:

(function () {
   ...one test
   });
(function () {
   ...anothertest
   });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接