最新消息: 电脑我帮您提供丰富的电脑知识,编程学习,软件下载,win7系统下载。

我如何测试使用Sinon等待的诺言(不是刚刚创建的)?

IT培训 admin 2浏览 0评论

我如何测试使用Sinon等待的诺言(不是刚刚创建的)?

假设我有一个功能:

const someAction = async(): Promise<string> => {
    /* do stuff */
};

而且我有一些代码只需执行此操作,而忽略结果。但是我有一个错误-我不想采取任何行动:

someAction();

相反,应该看起来像这样:

await someAction();

现在,我可以检查是否已执行此操作:

const actionStub = sinon.stub(someAction);
expect(actionStub).to.have.been.calledWith();

但是检查此承诺是否已被执行的最简洁方法是什么?

我知道我自己如何实现,但是我怀疑它一定已经在sinon或sinon-chai中实现了,我什么都找不到。

回答如下:

我当然可以说在sinon或sinon-chai中什么都没有。

这是在不使用结果的情况下测试任何基于承诺的功能所固有的困难。如果使用了结果,则您知道必须先解决诺言,然后才能继续进行所述结果。如果不是这样,那么事情将变得更加复杂,并且超出了sinon可以通过简单的存根为您完成的工作范围。

天真的方法是使用伪造的动作对动作进行存根,该动作设置了一些变量(对于您的测试是局部的)来跟踪状态。像这样:

let actionComplete = false;
const actionStub = sinon.stub(someAction).callsFake(() => {
    return new Promise((resolve) => {
        setImmediate(() => {
            actionComplete = true;
            resolve();
        });
    });
});

expect(actionStub).to.have.been.calledWith();
expect(actionComplete).to.be.true;

当然,这里的问题是等待any承诺(不一定是这个特定承诺)将通过此测试,因为变量将在操作循环的下一步进行设置,而不管是什么导致了等待下一步。

例如,您可以在被测试的代码中通过类似这样的操作来通过:

someAction();
await new Promise((resolve) => {
    setImmediate(() => resolve());
});

一种更强大的方法,尽管可能会更麻烦一些,但是将创建两个单独的测试。一个在诺言解决的地方,另一个在诺言拒绝的地方。您可以进行测试以确保拒绝会导致包含函数被拒绝而出现相同的错误,如果未await特定的承诺,则不可能。

const actionStub = sinon.stub(someAction).resolves();

// In one test
expect(actionStub).to.have.been.calledWith();

// In another test
const actionError = new Error('omg bad error');
actionStub.rejects(err);

// Assuming your test framework supports returning promises from tests.
return functionUnderTest()
    .then(() => {
        throw new Error('Promise should have rejected');
    }, (err) => {
        expect(err).to.equal(actionError);
    });

[一些断言库和扩展(也许是按承诺的那样)可能有一种方法来清理在那里使用已废止的诺言。我不想过多地假设您使用的工具,只是想确保这个想法能够得到传播。

我如何测试使用Sinon等待的诺言(不是刚刚创建的)?

假设我有一个功能:

const someAction = async(): Promise<string> => {
    /* do stuff */
};

而且我有一些代码只需执行此操作,而忽略结果。但是我有一个错误-我不想采取任何行动:

someAction();

相反,应该看起来像这样:

await someAction();

现在,我可以检查是否已执行此操作:

const actionStub = sinon.stub(someAction);
expect(actionStub).to.have.been.calledWith();

但是检查此承诺是否已被执行的最简洁方法是什么?

我知道我自己如何实现,但是我怀疑它一定已经在sinon或sinon-chai中实现了,我什么都找不到。

回答如下:

我当然可以说在sinon或sinon-chai中什么都没有。

这是在不使用结果的情况下测试任何基于承诺的功能所固有的困难。如果使用了结果,则您知道必须先解决诺言,然后才能继续进行所述结果。如果不是这样,那么事情将变得更加复杂,并且超出了sinon可以通过简单的存根为您完成的工作范围。

天真的方法是使用伪造的动作对动作进行存根,该动作设置了一些变量(对于您的测试是局部的)来跟踪状态。像这样:

let actionComplete = false;
const actionStub = sinon.stub(someAction).callsFake(() => {
    return new Promise((resolve) => {
        setImmediate(() => {
            actionComplete = true;
            resolve();
        });
    });
});

expect(actionStub).to.have.been.calledWith();
expect(actionComplete).to.be.true;

当然,这里的问题是等待any承诺(不一定是这个特定承诺)将通过此测试,因为变量将在操作循环的下一步进行设置,而不管是什么导致了等待下一步。

例如,您可以在被测试的代码中通过类似这样的操作来通过:

someAction();
await new Promise((resolve) => {
    setImmediate(() => resolve());
});

一种更强大的方法,尽管可能会更麻烦一些,但是将创建两个单独的测试。一个在诺言解决的地方,另一个在诺言拒绝的地方。您可以进行测试以确保拒绝会导致包含函数被拒绝而出现相同的错误,如果未await特定的承诺,则不可能。

const actionStub = sinon.stub(someAction).resolves();

// In one test
expect(actionStub).to.have.been.calledWith();

// In another test
const actionError = new Error('omg bad error');
actionStub.rejects(err);

// Assuming your test framework supports returning promises from tests.
return functionUnderTest()
    .then(() => {
        throw new Error('Promise should have rejected');
    }, (err) => {
        expect(err).to.equal(actionError);
    });

[一些断言库和扩展(也许是按承诺的那样)可能有一种方法来清理在那里使用已废止的诺言。我不想过多地假设您使用的工具,只是想确保这个想法能够得到传播。

发布评论

评论列表 (0)

  1. 暂无评论