javascript 如何通过expect.js async done() 出错的测试?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19339038/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 15:14:47  来源:igfitidea点击:

how to pass a test with expect.js async done() taking an error?

javascript

提问by rm.rf.etc

Mocha website states:

摩卡网站指出:

"To make things even easier, the done() callback accepts an error, so we may use this directly: [see their example]"

“为了让事情更简单,done() 回调接受一个错误,所以我们可以直接使用它:[参见他们的例子]”

So lets try that:

所以让我们尝试一下:

it('works',function(done){
  expect(1).to.be(1)
  done( new Error('expected error') )
})
/* Insert the error manually for testing and clarity. */

run it and:

运行它并:

1 failing

1) works:
 Error: expected error
  at Context.<anonymous>
  [stack trace]

How do we make the test pass when the error response is the desired result?

当错误响应是期望的结果时,我们如何使测试通过?

回答by slebetman

That's not async. The callback function is just there for you to inform mocha that you're testing async code and so mocha shouldn't run the next test until you call the callback function. This is an example of how to use the callback function:

那不是异步的。回调函数只是让您通知 mocha 您正在测试异步代码,因此在您调用回调函数之前, mocha 不应运行下一个测试。这是如何使用回调函数的示例:

it('works',function(done){
    setTimeout(function(){
        // happens 0.5 seconds later:
        expect(1).to.be(1);
        done(); // this tells mocha to run the next test
    },500);
});

Also, mocha does not handle any form of exceptions, async or otherwise. It leaves that up to an exception library of your choosing. In your case you're using expect.js? If so, expect handles expected errors via the throwExceptionmethod (also called throwError):

此外,mocha 不处理任何形式的异常,异步或其他。这取决于您选择的异常库。在您的情况下,您正在使用expect.js? 如果是这样,expect 通过throwException方法(也称为throwError)处理预期的错误:

it('throws an error',function(done){
    expect(function(){
        throw new Error('expected error');
    }).to.throwError(/expected error/);
});

Now, in general async code in node.js don't throw errors. They pass errors to the callback as parameters instead. So to handle async errors you can simply check the err object:

现在,通常 node.js 中的异步代码不会抛出错误。他们将错误作为参数传递给回调。因此,要处理异步错误,您可以简单地检查 err 对象:

// using readFile as an example of async code to be tested:
it('returns an error',function(done){
    fs.readFile(filename, function (err, data) {
        expect(err).to.be.an(Error);
        done(); // tell mocha to run next test
    })
});

So use to.throwError()if you're checking synchronous errors and to.be.an(Error)if you're checking async errors.

因此,to.throwError()如果您正在检查同步错误和to.be.an(Error)检查异步错误,请使用。



Additional notes:

补充笔记:

The first time I saw this I was stumped. How can mocha know that the test is synchronous or asynchronous when the only difference is weather the function you pass to it accepts an argument or not? In case you're like me and are scratching your head wondering how, I learned that all functions in javascript have a lengthproperty that describes how many arguments it accepts in its declaration. No, not the arguments.lengththing, the function's own length. For example:

我第一次看到这个的时候被难住了。当唯一的区别是传递给它的函数是否接受参数时,mocha 如何知道测试是同步还是异步?如果您像我一样正在挠头想知道如何做,我了解到 javascript 中的所有函数都有一个length属性来描述它在声明中接受多少个参数。不,不是arguments.length东西,是函数自己的length。例如:

function howManyArguments (fn) {
    console.log(fn.length);
}

function a () {}
function b (x) {}
function c (x,y,z) {}

howManyArguments(a); // logs 0
howManyArguments(b); // logs 1
howManyArguments(c); // logs 3
howManyArguments(howManyArguments); // logs 1
howManyArguments(function(x,y){}); // logs 2

So mocha basically checks the function's length to determine weather to treat it as a synchronous function or asynchronous function and pauses execution waiting for the done()callback if it's asynchronous.

所以 mocha 基本上检查函数的长度以确定天气将其视为同步函数或异步函数,done()如果它是异步的,则暂停执行等待回调。



Even more additional notes:

更多附加说明:

Mocha, like most other js unit test runners and libraries, work by catching errors. So it expects functions like expect(foo).to.be.an.integer()to throw an error if the assertion fails. That's how mocha communicates with assertion libraries like expect or chai.

Mocha 与大多数其他 js 单元测试运行器和库一样,通过捕获错误来工作。因此,它期望expect(foo).to.be.an.integer()在断言失败时抛出错误之类的函数。这就是 mocha 如何与像 expect 或 chai 这样的断言库进行通信。

Now, as I mentioned above, a common idiom in node is that async functions don't throw errors but passes an error object as the first argument. When this happens mocha cannot detect the error and so can't detect a failing test. The work-around to this is that if you pass the error object from the async code to the callback function it will treat it the same as a thrown error.

现在,正如我上面提到的,节点中的一个常见习惯用法是异步函数不会抛出错误,而是将错误对象作为第一个参数传递。发生这种情况时, mocha 无法检测到错误,因此无法检测到失败的测试。对此的解决方法是,如果您将错误对象从异步代码传递给回调函数,它会将其视为抛出的错误。

So, taking one of my examples above:

因此,以我上面的示例之一为例:

it('executes without errors',function(done){
    fs.readFile(filename, function (err, data) {
        done(err); // if err is undefined or null mocha will treat
                   // it as a pass but if err is an error object
                   // mocha treats it as a fail.
    })
});

Or simply:

或者干脆:

it('executes without errors',function(done){
    fs.readFile(filename,done);
});    

Strictly speaking, this feature is a bit redundant when used with libraries like expect.js which allows you to manually check the returned error object but it's useful for when your assertion library can't check the error object (or when you don't really care about the result of the async function but just want to know that no errors are thrown).

严格来说,这个特性在与诸如 expect.js 之类的库一起使用时有点多余,它允许您手动检查返回的错误对象,但是当您的断言库无法检查错误对象时(或者当您真的不检查错误对象时),它很有用关心异步函数的结果,但只想知道没有抛出错误)。

回答by LuxLee

You can also return your async such as promise as below.

您还可以返回异步,例如如下承诺。

it('Test DNA', () => {
    return resolvedPromise.then( (result)=>{
       expect(result).to.equal('He is not a your father.');      
    },(err)=>{
       console.log(err);
    });
});