[英]how to test a angular service which named as 'sample.Svc' in my modules using mocha+chai
[英]How to write a test using Mocha+Chai to expect an exception from setTimeout?
我有以下内容:
it('invalid use', () => {
Matcher(1).case(1, () => {});
});
该case
方法应该在一些延迟后抛出,我该如何为Mocha / Chai描述它,这就是我想要的-测试应该通过(并且在未引发异常时必须不通过)?
考虑case
方法的限制,无法更改。
出于测试目的,它应等效于:
it('setTimeout throw', _ => {
setTimeout(() => { throw new Error(); }, 1); // this is given, cannot be modified
});
我试过了:
it('invalid use', done => {
Matcher(1).case(1, () => {});
// calls done callback after 'case' may throw
setTimeout(() => done(), MatcherConfig.execCheckTimeout + 10);
});
但这并不能真正帮助我,因为测试行为已完全还原-当未引发case
异常( setTimeout
)时,它通过(应该失败),而当引发异常时,测试失败(应该成功)。
我在某处读到有人提到全局错误处理程序,但如果可能的话,我想使用Mocha和/或Chai彻底解决此问题(我想Mocha已经在以某种方式使用它了)。
您不能从异步回调中处理异常,例如,请参见从setTimeout处理错误 。 这与ECMAScript使用的执行模型有关。 我想捕获它的唯一方法实际上是采用某些特定于环境的全局错误处理,例如Node.js中的process.on('uncaughtException', ...)
。
但是,如果将函数转换为Promises,则可以使用Chai插件chai-as-promsied轻松测试它:
import * as chai from 'chai';
import chaiAsPromised = require('chai-as-promised');
chai.use(chaiAsPromised);
const expect = chai.expect;
it('invalid use', async () => {
await expect(Matcher(1).case(1, () => {})).to.eventually.be.rejected;
});
任何摩卡之类的语句before
, after
还是it
会异步如果返回一个承诺工作。 我通常将以下内容用于异步测试。 如果您希望异步功能花费2秒钟以上的时间,也不要忘记设置超时this.timeout(...)
。
it('some test', () => {
return new Promise(function(resolve,reject){
SomeAsyncFunction(function(error,vals) {
if(error) {
return reject(error);
} else {
try {
//do some chai tests here
} catch(e) {
return reject(e);
}
return resolve();
}
});
});
});
专门针对您的情况,由于我们希望在一段时间后会引发一些错误(假设由于引发了异常,您提供给.case
的空回调不应该运行),因此您可以编写以下内容:
it('invalid use', () => {
//define the promise to run the async function
let prom = new Promise(function(resolve,reject){
//reject the promise if the function does not throw an error
//note I am assuming that the callback won't run if the error is thrown
//also note this error will be passed to prom.catch so need to do some test to make sure it's not the error you are looking for.
Matcher(1).case(1, () => {return reject(new Error('did not throw'))});
});
prom.catch(function(err){
try {
expect(err).to.be.an('error');
expect(err.message).to.not.equal('did not throw');
//more checks to see if err is the error you are looking for
} catch(e) {
//err was not the error you were looking for
return Promise.reject(e);
}
//tests passed
return Promise.resolve();
});
//since it() receives a promise as a return value it will pass or fail the test based on the promise.
return prom;
});
如果您测试的代码使用抛出的回调调用setTimeout
,但没有人捕获到此异常,则:
1)此代码已损坏
2)看到该问题的唯一方法是平台全局异常处理程序,例如用户ComFreek提到的process.on('uncaughtException'
最后的机会是将setTimeout
存根以进行测试(例如,使用sinon.stub
)或仅手动进行sinon.stub
。
在这样的存根setTimeout
您可以装饰超时处理程序,检测异常并调用适当的断言。
注意,这是万不得已的解决方案-您的应用代码已损坏,应该进行修复以正确传播错误,不仅用于测试,而且……要成为好的代码。
伪代码示例:
it('test', (done) => { const originalSetTimeout = setTimeout; setTimeout = (callback, timeout) => { originalSetTimeout(() => { try { callback(); } catch(error) { // CONGRATS, you've intercepted exception // in _SOME_ setTimeout handler } }, timeout) } yourTestCodeThatTriggersErrorInSomeSetTimeoutCallback(done); })
注意2:我故意没有编写适当的异步清理代码,这是一项家庭作业。 再次,请参见sinon.js
及其sandbox
注意3:它将在测试期间捕获所有setTimeout
调用。 当心,有龙。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.