javascript - 尝试测试异步函数抛出时,Jest 测试失败
问题描述
我有一个异步函数,我想测试两者:成功和失败。成功时函数返回一个字符串,失败时抛出。我在测试失败方面失败得很惨。这是我的代码:
- getKmlFileName.test.js
我已通过注释失败的代码并将结果添加到注释中来禁用
'use strict';
const path = require('path');
const fs = require('fs');
const getKmlFilename = require('./getKmlFileName.js');
const createGoodFolder = () => {
const folderPath = fs.mkdtempSync('/tmp/test-getKmlFilename-');
const fileDescriptor = fs.openSync(path.join(folderPath, 'doc.kml'), 'w');
fs.closeSync(fileDescriptor);
return folderPath;
};
const createEmptyFolder = () => fs.mkdtempSync('/tmp/test-getKmlFilename-');
describe('/app/lib/getKmlFilename', () => {
// Success tests
test('Should return a KML filename', async () => {
const result = await getKmlFilename(createGoodFolder());
expect(result).toMatch(/\.kml$/);
});
// Failure tests
test('Should throw if no KML files in folder', () => {
// Expected one assertion to be called but received zero assertion calls.
// expect.assertions(1);
// expect(function).toThrow(undefined)
// Received value must be a function, but instead "object" was found
//return getKmlFilename(createEmptyFolder())
// .catch(e => expect(e).toThrow());
// expect(string)[.not].toMatch(expected)
// string value must be a string.
// Received:
// object:
// [Error: No valid KML file in /tmp/test-getKmlFilename-j2XxQ4]
return getKmlFilename(createEmptyFolder())
.catch(e => expect(e).toMatch('No valid KML file in'));
});
test('Should throw if no KML files in folder - try/catch version',
async () => {
// Expected one assertion to be called but received zero assertion calls.
// expect.assertions(1);
try {
const result = await getKmlFilename(createEmptyFolder());
} catch (e) {
// Received value must be a function, but instead "object" was found
// expect(e).toThrow();
// expect(string)[.not].toMatch(expected)
// string value must be a string.
// Received:
// object:
// [Error: No valid KML file in /tmp/test-getKmlFilename-3JOUAX]
expect(e).toMatch('No valid KML file in');
}
});
});
如您所见,没有任何效果。我相信我的测试几乎是第一个失败测试的Promises示例和最后一个失败测试的Async/Await示例的精确副本,但是没有一个有效。
我相信 Jest 文档中示例的不同之处在于它们展示了如何测试一个函数throw
以及如何测试一个 Promise reject
。但我的诺言通过投掷来拒绝。
检查节点控制台中的功能,我得到以下日志:
// import function
> getKml = require('./getKmlFileName.js')
[AsyncFunction: getKmlFilename]
// trying it with a proper folder shows we get a Promise
> getKml('/tmp/con')
Promise {
<pending>,
domain:
Domain {
domain: null,
_events: { error: [Function: debugDomainError] },
_eventsCount: 1,
_maxListeners: undefined,
members: [] } }
// trying it with a failing folder shows it's a rejected promise which throws
> getKml('/tmp/sin')
Promise {
<pending>,
domain:
Domain {
domain: null,
_events: { error: [Function: debugDomainError] },
_eventsCount: 1,
_maxListeners: undefined,
members: [] } }
> (node:10711) UnhandledPromiseRejectionWarning: Error: No valid KML file in /tmp/sin
at getKmlFilename (/home/flc/soft/learning/2018.06.08,jest/getKmlFileName.js:14:11)
at <anonymous>
at process._tickDomainCallback (internal/process/next_tick.js:228:7)
(node:10711) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:10711) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
正如您从内联注释中看到的那样,该函数正在做它应该做的,但是我不知道如何在 Jest 中测试它。任何帮助将不胜感激。
我觉得这里的代码看起来太复杂了,我准备了一个存储库,其中包含我学习 Jest 的不幸
更新 2018.06.12:
不知何故,我的消息被打乱并丢失了第一部分,这是我正在尝试测试的实际代码,对此我深表歉意,这里是:
获取KmlFileName.js
'use strict'; const globby = require('globby'); const path = require('path'); const getKmlFilename = async (workDir) => { const pattern = path.join(workDir, '**/*.kml'); const files = await globby(pattern); if (files && files.length > 0) { // Return first KML found, if there are others (improbable), ignore them return path.basename(files[0]); } else { throw new Error(`No valid KML file in ${workDir}`); } }; module.exports = getKmlFilename;
解决方案
在您的第一次测试中:
return getKmlFilename(createEmptyFolder())
.catch(e => expect(e).toMatch('No valid KML file in'));
如果 Promise 解决,它不会抱怨。
在第二次测试中
try {
const result = await getKmlFilename(createEmptyFolder());
} catch (e) {
...
}
如果 Promise 解决,它也不会抱怨,因为它不会进入 catch 块。
要测试 Promise,请问自己以下问题:
- 承诺应该成功(解决)还是失败(拒绝)?
- 你的结果或拒绝值是
Error
一个对象还是一个常规对象?
开玩笑地说,你应该能够做到这一点:
- 解析为常规对象:
expect(yourThing()).resolves.toMatchSnapshot()
- 解决错误(从未见过):
expect(yourThing()).resolves.toThrow(/something/)
- 拒绝错误:
expect(yourThing()).rejects.toThrow(/something/)
- 拒绝常规对象(您确定要这个吗?):
expect(yourThing()).rejects.toMatchSnapshot()
请注意,异步函数总是返回一个值(一个 Promise 对象),因此“通常”expect(() => yourThing()).toThrow()
将不起作用。您需要先等待 Promise 的结果(通过使用resolves
or rejects
)然后对其进行测试。
推荐阅读
- assembly - 将 xmm 寄存器的低两个 32 位浮点数扩展为整个 xmm 寄存器
- javascript - [JavaScript]为什么进度条 addeventlistener 不起作用?
- node.js - 无法读取未定义 discord.js 的属性“获取”
- html - 为什么我的列表超出表格单元格?
- kivy - 如何在 KivyMD 文本字段中更改提示文本的字体名称?
- javascript - 当我声明一个类字段时,为什么 jshint 会抛出错误?
- c - 用 C 复位 PIC24FJ128GA010
- javascript - 如何为 fullcalendar 3.9 / bootstrap 4 的事件添加工具提示
- swift - 保存文件后 XCode 12 冻结
- html - 如何在 HTML 中将其转换为 SCSS 内联样式