chai-as-promised:单个测试中的多个 expect 语句
chai-as-promised: multiple expect statements in a single test
我正在使用 chai-as-promised 来测试一些承诺。我的问题是我不确定如何在单个测试中有多个 expect 语句。为了 expect().to.be.fulfilled
正常工作,我需要 return 它,像这样:
it('test', () => {
return expect(promise).to.be.fulfilled
}
... 或者使用 notify
,像这样:
it('test', (done) => {
expect(promise).to.be.fulfilled.notify(done)
}
当我有另一件事需要检查时,例如某个函数被调用时,问题就来了,如下所示:
it('test', (done) => {
var promise = doSomething()
expect(sinon_function_spy.callCount).to.equal(1)
expect(promise).to.be.fulfilled.notify(done)
})
这里的问题是,因为 doSomething()
是异步的,所以当我调用 expect
时,对 sinon_function_spy
的调用可能还没有发生,这使得这个测试不稳定。如果我使用 then
,像这样:
it('test', (done) => {
var promise = doSomething()
promise.then(() => {
expect(sinon_function_spy.callCount).to.equal(1)
})
expect(promise).to.be.fulfilled.notify(done)
})
然后测试技术上按预期通过和失败,但它会失败,因为承诺被拒绝,由于 then
调用中抛出的异常。类似的,如果我遇到promise预计会被reject的情况:
it('test', (done) => {
var promise = doSomething()
promise.then(() => {
expect(sinon_function_spy.callCount).to.equal(1)
})
expect(promise).to.be.rejected.notify(done)
})
然后对 sinon_function_spy
的检查永远不会被调用,因为承诺被拒绝并且不会调用 then
。
如何让 expect
语句可靠地执行并 return 正确的值?
如果您使用 mocha 或 jest 作为您的测试框架,您可以 return 在您的 then()
块中包含预期的承诺:
it('test', () => {
return doSomething().then( () => {
expect(sinon_function_spy.callCount).to.equal(1);
});
});
直到承诺成功完成且 expect
已 运行 后,此测试才会结束。如果您使用的是 jasmine,则可以使用 jasmine-promises
包来获得相同的功能。
对于相反的情况,我建议创建一个包装器来反转 promise 的极性:
function reverse( promise ) {
//use a single then block to avoid issues with both callbacks triggering
return promise.then(
() => { throw new Error("Promise should not succeed"); }
e => e; //resolves the promise with the rejection error
);
}
现在你可以做
it('test', () => {
return reverse( doSomethingWrong() ).then( error => {
expect( error.message ).to.equal("Oh no");
});
});
在想要断言 Promise 已实现 和 调用按预期执行的情况下,您实际上不需要将第一部分作为断言。只要你返回它,如果 Promise 拒绝,mocha 测试用例本身就会失败:
it('test', () => {
return doSomething()
.then(() => {
expect(sinon_function_spy.callCount).to.equal(1)
});
});
如果 doSomething()
返回的 Promise 被拒绝,测试用例也会被拒绝。如果 expect
断言失败,它也会使带有该失败断言的测试用例失败。如果你想更明确一点:
it('test', () => {
return doSomething()
.then(() => {
expect(sinon_function_spy.callCount).to.equal(1)
}, err => {
expect(err).to.not.exist;
});
});
...您可以捕获错误。请注意,使用这种带有两个回调的 then
风格,第一个回调中失败的断言将不会到达第二个回调,因此只有 Mocha 会看到失败的断言。
以下是如何执行预期失败的 Promise:
it('test', () => {
return doSomething()
.then(() => {
throw new Error('Promise should not have resolved');
}, err => {
expect(err).to.exist;
expect(sinon_function_spy.callCount).to.equal(1)
});
})
一种实现多重期望的方法
it('should fail if no auth', () => {
const promise = chai.request(server).get('/albums');
return expect(promise).to.be.rejected.then(() => {
return promise.catch(err => {
expect(err).not.to.be.null;
expect(err.response).to.have.status(401);
expect(err.response).to.be.a.json;
});
});
});
我发现最好的方法是这样的:
it('test', async () => {
await expect(promise1).to.eventually.be.equal(1);
await expect(promise2).to.eventually.be.equal(2);
})
我正在使用 chai-as-promised 来测试一些承诺。我的问题是我不确定如何在单个测试中有多个 expect 语句。为了 expect().to.be.fulfilled
正常工作,我需要 return 它,像这样:
it('test', () => {
return expect(promise).to.be.fulfilled
}
... 或者使用 notify
,像这样:
it('test', (done) => {
expect(promise).to.be.fulfilled.notify(done)
}
当我有另一件事需要检查时,例如某个函数被调用时,问题就来了,如下所示:
it('test', (done) => {
var promise = doSomething()
expect(sinon_function_spy.callCount).to.equal(1)
expect(promise).to.be.fulfilled.notify(done)
})
这里的问题是,因为 doSomething()
是异步的,所以当我调用 expect
时,对 sinon_function_spy
的调用可能还没有发生,这使得这个测试不稳定。如果我使用 then
,像这样:
it('test', (done) => {
var promise = doSomething()
promise.then(() => {
expect(sinon_function_spy.callCount).to.equal(1)
})
expect(promise).to.be.fulfilled.notify(done)
})
然后测试技术上按预期通过和失败,但它会失败,因为承诺被拒绝,由于 then
调用中抛出的异常。类似的,如果我遇到promise预计会被reject的情况:
it('test', (done) => {
var promise = doSomething()
promise.then(() => {
expect(sinon_function_spy.callCount).to.equal(1)
})
expect(promise).to.be.rejected.notify(done)
})
然后对 sinon_function_spy
的检查永远不会被调用,因为承诺被拒绝并且不会调用 then
。
如何让 expect
语句可靠地执行并 return 正确的值?
如果您使用 mocha 或 jest 作为您的测试框架,您可以 return 在您的 then()
块中包含预期的承诺:
it('test', () => {
return doSomething().then( () => {
expect(sinon_function_spy.callCount).to.equal(1);
});
});
直到承诺成功完成且 expect
已 运行 后,此测试才会结束。如果您使用的是 jasmine,则可以使用 jasmine-promises
包来获得相同的功能。
对于相反的情况,我建议创建一个包装器来反转 promise 的极性:
function reverse( promise ) {
//use a single then block to avoid issues with both callbacks triggering
return promise.then(
() => { throw new Error("Promise should not succeed"); }
e => e; //resolves the promise with the rejection error
);
}
现在你可以做
it('test', () => {
return reverse( doSomethingWrong() ).then( error => {
expect( error.message ).to.equal("Oh no");
});
});
在想要断言 Promise 已实现 和 调用按预期执行的情况下,您实际上不需要将第一部分作为断言。只要你返回它,如果 Promise 拒绝,mocha 测试用例本身就会失败:
it('test', () => {
return doSomething()
.then(() => {
expect(sinon_function_spy.callCount).to.equal(1)
});
});
如果 doSomething()
返回的 Promise 被拒绝,测试用例也会被拒绝。如果 expect
断言失败,它也会使带有该失败断言的测试用例失败。如果你想更明确一点:
it('test', () => {
return doSomething()
.then(() => {
expect(sinon_function_spy.callCount).to.equal(1)
}, err => {
expect(err).to.not.exist;
});
});
...您可以捕获错误。请注意,使用这种带有两个回调的 then
风格,第一个回调中失败的断言将不会到达第二个回调,因此只有 Mocha 会看到失败的断言。
以下是如何执行预期失败的 Promise:
it('test', () => {
return doSomething()
.then(() => {
throw new Error('Promise should not have resolved');
}, err => {
expect(err).to.exist;
expect(sinon_function_spy.callCount).to.equal(1)
});
})
一种实现多重期望的方法
it('should fail if no auth', () => {
const promise = chai.request(server).get('/albums');
return expect(promise).to.be.rejected.then(() => {
return promise.catch(err => {
expect(err).not.to.be.null;
expect(err.response).to.have.status(401);
expect(err.response).to.be.a.json;
});
});
});
我发现最好的方法是这样的:
it('test', async () => {
await expect(promise1).to.eventually.be.equal(1);
await expect(promise2).to.eventually.be.equal(2);
})