跳转到主要内容
版本:26.倍

测试异步代码

在JavaScript中执行异步代码是很常见的。当你有以异步方式运行的代码时,Jest需要知道当前它测试的代码是否已完成,然后它可以转移到另一个测试。笑话有若干方法处理这种情况。

回调#

最常见的异步模式是回调函数。

例如,假设您有一个fetchData(回调)函数,获取一些数据并在完成时调用回调(数据)。你期望返回的数据是一个字符串“花生酱”

默认情况下,一旦到达运行上下文底部,jest测试立即结束。这样意味着这个测试将不能按预期工作。

// 不要这样做!
//不要这样做!
测试 ( “数据是花生酱” , ( ) = > {
函数 回调 ( 数据 ) {
预计 ( 数据 ) 托比 ( “花生酱” ) ;
}
fetchData ( 回调 ) ;
} ) ;

问题在于一旦fetchData执行结束,此测试就在没有调用回调函数前结束。

还有另一种形式的测试,解决此问题。使用单个参数调用完成,而不是将测试放在一个空参数的函数。开玩笑会等完成回调函数执行结束后,结束测试。

测试 ( “数据是花生酱” , 完成 = > {
函数 回调 ( 数据 ) {
试一试 {
预计 ( 数据 ) 托比 ( “花生酱” ) ;
完成 ( ) ;
} ( 错误 ) {
完成 ( 错误 ) ;
}
}
fetchData ( 回调 ) ;
} ) ;

(完成)函数从未被调用,测试用例会正如你预期的那样执行失败(显示超时错误)。

预计执行失败,它会抛出一个错误,后面的(完成)不再执行。若我们想知道测试用例为何失败,我们必须将预计放入试一试中,将错误传递给中的完成函数。否则,最后控制台将显示一个超时错误失败,不能显示我们在期望(数据)中接收的值。

承诺#

如果您的代码使用promise,则有一种更直接的方法来处理异步测试。从测试中返回一个承诺,Jest将等待这个承诺解决。如果承诺被拒绝,则测试将自动失败。从测试中返回一个承诺,Jest将等待这个承诺解决。如果承诺被拒绝,则测试将自动失败。

举个例子,比方说,fetchData承诺,使用代替回调的话,返回值是应该解析为字符串“花生酱”的承诺。我们可以使用下面的测试代码︰

测试 ( “数据是花生酱” , ( ) = > {
返回 fetchData ( ) 然后 ( 数据 = > {
预计 ( 数据 ) 托比 ( “花生酱” ) ;
} ) ;
} ) ;

一定不要忘记把承诺作为返回值⸺如果你忘的了返回语句的话,在fetchData返回的这个承诺被解决,那么()有机会执行之前,测试就已经被视为已经完成了。

如果你期望一个承诺被拒绝,使用.catch方法。请确保添加expect.assertions来验证一定数量的断言被调用。请确保添加expect.assertions来验证一定数量的断言被调用。否则,一个兑现的承诺就不会在测试中失败。

测试 ( '取回失败,有错误' , ( ) = > {
预计 断言 ( 1 ) ;
返回 fetchData ( ) ( e = > 预计 ( e ) toMatch ( “错误” ) ) ;
} ) ;

.resolves/.rejects#

您还可以使用.resolves匹配器在您期望的声明,开玩笑会等待这一承诺来解决。如果承诺被拒绝,则测试将自动失败。

测试 ( “数据是花生酱” , ( ) = > {
返回 预计 ( fetchData ( ) ) 解决了 托比 ( “花生酱” ) ;
} ) ;

一定不要忘记把整个断言作为返回值返回⸺如果你忘的了返回语句的话,在fetchData返回的这个承诺变更为解决状态,然后()有机会执行之前,测试就已经被视为已经完成了。

如果你期望一个承诺被拒绝,使用.rejects匹配器。它参照工程.resolves匹配器。它参照工程.resolves匹配器。如果承诺被拒绝,则测试将自动失败。

测试 ( '取回失败,有错误' , ( ) = > {
返回 预计 ( fetchData ( ) ) 拒绝 toMatch ( “错误” ) ;
} ) ;

异步/等待#

或者,您可以在测试中使用异步等待。要编写一个异步测试,请使用异步传递给的函数前面的关键字测试。例如,可以用来测试相同的fetchData方案︰例如,可以用来测试相同的fetchData方案︰

测试 ( “数据是花生酱” , 异步 ( ) = > {
常量 数据 = 等待 fetchData ( ) ;
预计 ( 数据 ) 托比 ( “花生酱” ) ;
} ) ;
测试 ( '取回失败,有错误' , 异步 ( ) = > {
预计 断言 ( 1 ) ;
试一试 {
等待 fetchData ( ) ;
} ( e ) {
预计 ( e ) toMatch ( “错误” ) ;
}
} ) ;

您可以组合异步等待.resolves.rejects

测试 ( “数据是花生酱” , 异步 ( ) = > {
等待 预计 ( fetchData ( ) ) 解决了 托比 ( “花生酱” ) ;
} ) ;
测试 ( '取回失败,有错误' , 异步 ( ) = > {
等待 预计 ( fetchData ( ) ) 拒绝 toMatch ( “错误” ) ;
} ) ;

在这些情况下,异步等待是promise示例使用的相同逻辑的有效语法糖。

这些表单没有一种特别优于其他表单,您可以跨代码库甚至在单个文件中混合和匹配它们。这取决于您认为哪种风格使您的测试更简单。这只取决于哪种形式更能使您的测试变得简单。