「如何实现流动式软件发布」线上课堂开课啦,快来报名参与课堂抽奖吧~ 了解详情
写点什么

测试微服务之单元测试

2017 年 11 月 05 日

上一篇文章里,我们介绍了测试金字塔以及如何将它应用在分布式系统里。

这篇文章将关注测试金字塔里的单元测试层,并探讨如何高效地为分布式系统(如微服务)构建单元测试。

定义测试边界

定义测试边界是实现高效测试的第一步。测试的目的是为了验证边界里“黑盒”的行为是否符合预期,我们向黑盒输入数据,然后验证输出的正确性。

在单元测试里,黑盒指的是函数或者类的方法,目的是单独测试特定代码块的行为。为了更好地理解这个概念,我们以简单的注册功能为例:

我们可以看到这个函数包含了一些输入和输出。这个函数接受基本的用户注册信息作为输入参数,并返回新创建的用户ID。

不过这里也有一些不是很明显的输入数据。这个函数调用了另个外部函数:一个向数据库插入数据,一个对密码进行散列和持久化。在某些情况下,数据库可能会返回错误。比如,因为用户名唯一性问题导致数据库插入失败,又或者需要通过调用外部的微服务进行密码散列,如果网络连接出现问题或密码散列服务因发生过载导致服务超时,那么密码散列函数就会返回错误。

为了全面测试用户注册功能,单元测试所要做的不仅仅是简单地传进去不同的输入参数,它还要能够让外部依赖项能够使用这些输入来验证函数的行为是否符合预期。在测试函数的错误处理逻辑时,这点很重要的。

Stub 和 Mock

为了制造各种输入数据,需要使用 stub,也叫作 mock。这个可以使用依赖注入或方法搅拌(swizzle)来实现。测试框架在运行被测试的函数时可以确保对底层依赖项的调用会被重定向到 stub 上:

我们可以使用 stub 来达到各种目的:

  • stub 可以什么事也不做。这样可以加快个别单元测试的速度,如果后续有其他单元测试可用于测试边界情况的话就可以这样做。

  • stub 可返回任意的值,用于模拟外部函数的输出。这在测试罕见的边界情况时会非常有用,比如有些错误场景很少会发生或者难以重现。

  • stub 也可以用于捕捉被测试函数欲传给外部函数的参数,或者把这些参数记录下来。这样就可以验证被测试函数需要调用哪些外部函数以及需要传给外部函数哪些参数。

测试分布式系统需要有一套很好的 stub,有了这些 stub,单元测试才能够在没有外部服务的情况下运行。下面列出了一些工具,用于创建各种 stub。

Node.js/JavaScript

Python

Go

Java

单元测试流程

单元测试的目的是为了给开发人员提供快速验证他们所写代码的行为。因为对外部依赖的调用使用了 stub,所以通常可以在几秒钟内就可以执行数千个单元测试。所以,开发人员可以把单元测试加入到他们的开发工作流当中,要么直接集成到他们的 IDE 里,要么通过终端命令行来运行。开发人员在编写代码的同时频繁地运行单元测试可以帮助他们及早地发现代码中的问题。

一旦开发人员养成了这样的习惯,那么就可以进行测试驱动开发了。开发人员在开发新特性之前会先准备好单元测试,在新特性被加进来之前,测试总是失败。在经过不断的测试和代码修改之后,一个完整的功能被开发出来了,最后再运行测试就能通过。

单元测试的作用不应局限于代码开发,它们也应该被集成到代码合并流程里。GitHub 支持一些主流持续集成服务器的状态检查。一般的流程是这样的:保护好“master”分支,不允许开发人员向该分支提交代码,而是让他们把代码提交到其他分支上。在将代码合并到 master 分支的时候,GitHub 要求先通过状态检查。

Jenkins、CircleCI 和 TravisCI 都提供了状态检查钩子(hook),它们会从分支上获取代码并运行单元测试。如果通过了,就允许合并代码,否则就不允许。

总结

单元测试是测试工具箱里的一个非常重要的工具。为了对分布式系统代码进行全面的单元测试,有必要利用一些支持 stub 的测试框架,用于模拟各种错误场景或外部依赖的各种响应。

查看英文原文 Microservice Testing: Unit Tests

2017 年 11 月 05 日 18:003220
用户头像

发布了 321 篇内容, 共 113.4 次阅读, 收获喜欢 114 次。

关注

评论

发布
暂无评论
发现更多内容

Mysql插入百万条数据

Java小咖秀

MySQL 运维 数据

CAP原理简述

刘志刚

推荐系统大规模特征工程与FEDB的Spark基于LLVM优化

范式AI云

spark Sparksql 推荐系统 LLVM FEDB

吴恩达推荐笔记:22张图总结深度学习全部知识

程序员生活志

学习 吴恩达

数据驱动 vs 关键字驱动:对UI自动化测试框架搭建的探索

Winfield

DevOps 敏捷 自动化测试

看动画学算法之:排序-插入排序

程序那些事

Java 数据结构 算法 插入排序

laravel redis队列不执行

kaer

laravel redis Queue

腾讯的ToB梦想

ToB行业头条

智慧4S店解决方案发布,看英特尔如何引领汽车销售行业变革

最新动态

人人都需要一份自己的「使用说明书」

非著名程序员

程序员 程序人生 提升认知 独立思考 自我思考

IDC2020 Q1通用服务器数据发布,浪潮信息成绩喜人

Geek_116789

Spring5-Reactor函数式编程

小技术君

spring reactor Spring5 springboot

阿里拍卖,能不能拍到点儿上?

ToB行业头条

如何把百万级别的订单根据金额排序

码哥字节

数据结构 排序算法

为什么我们需要制品管理?

Man

DevOps nexus 制品库管理 Artifactory

在前端如何玩转 Word 文档

阿宝哥

html markdown word

SpringBoot 入门:03 - 统一请求返回

封不羁

Java spring springboot

设计模式(1)—什么是设计模式?设计模式的六大原则是什么?

爱嘤嘤嘤斯坦

Java 程序员 编程语言 设计模式 23种设计模式

时间去哪了?

escray

自动化测试首先是一种工作文化

wangwei1237

自动化测试 测试文化

MobTech袤博与百度战略签约 携手布局数据智能产业新蓝图

Geek_116789

三大 OSS 缓存加速系统巅峰对决

苏锐

hadoop cache JuiceFS JindoFS Performance

抽象工厂模式

Leetao

Python 面试 设计模式

我在项目中是这样配置Vue的

前端有的玩

Java Vue 前端 框架设计

女员工被阿里录取工资二万六,辞职时被领导挽留:给你4万留下

程序员生活志

阿里 女程序员

抢滩新基建,百度还会输给阿里和腾讯吗?

ToB行业头条

计算机网络基础(一)---计算机网络概览篇

书旅

php laravel 计算机网络

《重学 Java 设计模式》PDF 出炉了 - 小傅哥,肝了50天写出18万字271页的实战编程资料

小傅哥

Java 设计模式 小傅哥 重构 代码质量

第6周-作业1

seng man

第6周-作业2-总结

seng man

设计模式六大原则

刘志刚

设计原则

测试微服务之单元测试-InfoQ