使用Jest快照测试api

你知道什么很烦人吗?API不匹配。

有一天,后台开发人员在没有通知前端开发人员的情况下更改了其中一个api。“我们认为dateCreated这个名字比created_at更好,”他们说。“我们昨天在单口相声会上不是告诉过你吗?”

然后,一切都崩溃了。

有涵盖UI代码的单元测试。有涵盖后端代码的单元测试。所有这些都已经过去了。然而,这个应用程序已经坏了。

在这篇文章中,我们将介绍如何使用Jest编写API测试,使用很少的代码,从而避免这种混乱。

没有端到端测试

缺少的是一组检查前端和后端是否正确集成的测试。

这些被称为端到端测试或验收测试,它们通常在浏览器级别上完成。像Selenium、Nightwatch或Capybara这样的工具可以驱动一个无头浏览器来登录、点击、填写表单,并确保一切正常运行。

但是,端到端(E2E)测试存在一些问题——它们速度慢、容易出错和脆弱。编写好selenium样式的浏览器自动化是需要技巧的。狡猾的计时错误可能会潜入,导致测试间歇失败。

如果测试显示:

加载用户配置文件页面并断言标记具有文本用户配置文件

如果你把它改成an,测试就会失败。

因此,在编写这样的测试时需要一种很好的平衡——您需要足够好的断言来验证功能,但又不需要太过具体,当您引入额外的命令时它们就会崩溃。什么的。

一个折衷方案:快照API测试

Facebook的Jest工具支持一种称为快照测试的测试方式,基本上:

您可以手动验证代码是否正常工作。编写一个快照测试并运行它。它保存了事物的文本表示。将快照签入源代码控制。之后,每次运行测试时,都会根据磁盘上的旧快照验证结果。如果它们不匹配,测试就会失败。

这通常应用于React组件(您可以在这里读到关于快照测试React组件的内容),但是可以获取任何内容的快照。任何JS对象都可以快照。

也就是说,你可以:

为结果做一个API调用快照,知道如果API快照通过,你的UI和后端是一致的

注意事项

如果您以前编写过单元测试,那么您可能已经模拟了API,使其不进行任何调用。在这些测试中,我们将其颠倒过来。我们希望对真实的服务器进行真实的API调用。

这意味着您需要运行一个后端服务器来运行这些测试。这有点复杂,但在贸易中,你会更有信心。

您还需要了解测试数据库,并确保在执行类似“创建3个事务,并验证GET /transactions返回3个事务”这样的操作之前,将其重置为一个已知的状态。在不清理数据库的情况下运行两次,测试将失败。

我不会在这里深入讨论如何设置所有这些,因为它将在很大程度上依赖于您自己的后端设置、CI设置等。

如果您决定尝试这种方法,请从简单的开始:针对“登录”或“创建”之类的内容编写测试,这些内容将对脏数据库具有弹性。如果您喜欢这种方法,那么您可以考虑解决数据库/CI/等问题。

例子

测试登录

这里有一些测试的理论“登录”服务:

隐藏,收缩,复制Codeimport * as API from ‘api’;

test(‘failed login (bad password)’, async () => {
let data;
try {
data = await API.login(‘me@example.com’, ‘wrong_password’);
fail();
} catch(e) {
expect(e.response.data.error).toMatchSnapshot();
}
});

test(‘failed login (bad username)’, async () => {
let data;
try {
data = await API.login(‘not-a-real-account@example.com’, ‘password’);
fail();
} catch(e) {
expect(e.response.data.error).toMatchSnapshot();
}
});

test(‘good login’, async () => {
try {
const response = await API.login(‘test-account@example.com’, ‘supersecret!’);
expect(response).toMatchSnapshot();
} catch(e) {
fail();
}
});

这些测试利用异步/等待使代码读取更像同步代码。

这里并没有发生太多奇妙的事情:每个测试都进行一个API调用,并断言结果(或错误)与快照匹配。

请记住,在第一次运行快照测试之前,必须验证API调用是否在工作。它们通常会与测试JS文件一起保存在其余的snapshots__文件夹中,所以你也可以检查它们的正确性(你也应该这样做)。

测试变化的事物

有时API响应可能包含一个自动递增的ID或时间戳。这些事情将导致快照测试每次都失败。

为了解决这个问题,下面是一个sanitize函数的示例,该函数接受一个对象和一个要进行sanitize的键数组。因为它使用了lodash的set函数,所以键可以引用“深层”属性,比如user.orders[0]。created_at如果必要的话。

隐藏,复制Codeimport * as _ from ‘lodash’;
import * as API from ‘api’;

function sanitize(data, keys) {
return keys.reduce((result, key) => {
const val = _.get(result, key);
if(!val || _.isArray(val) || _.isObject(val)) {
return result;
} else {
return .set(.cloneDeep(result), key, ‘[SANITIZED]’);
}
}, data);
}

test(‘createOrder’, async () => {
let order = await API.createOrder(‘Camera’, 47, 19.84);
order = sanitize(order, [‘id’, ‘created_at’]);
expect(order).toMatchSnapshot();
});

试试

我只是刚刚开始在我自己的项目中实现这种测试方法,但到目前为止它似乎很有前途。试一试吧,如果你这么做了,请留下评论。😃

Jest快照测试api最初由Dave Ceddia于2017年9月18日在Dave Ceddia上发布。

CodeProject上

本文转载于:http://www.diyabc.com/frontweb/news29970.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值