当前位置:网站首页>单元测试chapter6
单元测试chapter6
2022-07-27 04:33:00 【菜鸟晓晓】
Chapter6
本章涵盖了:
1.比较单元测试的风格
2.功能与六边形建筑的关系
3.过渡到基于输出的测试
第4章介绍了良好的单元测试的四个属性:防止回归,抵抗重构,快速反馈和可维护性。 这些属性构成参考框架,可用于分析特定的测试和单元测试方法。 在第5章中,我们分析了一种这样的方法:模拟的使用。
在本章中,我将相同的参考框架应用于单元测试样式的主题。 共有三种样式:基于输出,基于状态和基于通信的测试。 在这三种方法中,基于输出的样式将产生最高质量的测试,基于状态的测试是第二好的选择,并且基于通信的测试应仅偶尔使用。
不幸的是,您不能在所有地方都使用基于输出的测试样式。 它仅适用于以纯功能方式编写的代码。 但是不用担心 有一些技术可以帮助您将更多测试转换为基于输出的样式。 为此,您需要使用函数式编程原理将基础代码重组为函数式架构。
请注意,本章并未深入探讨函数式编程主题。 尽管如此,希望在本章结束之前,您能对函数式编程与基于输出的测试之间的关系有一个直观的了解。 您还将学习如何使用基于输出的样式编写更多的测试,以及功能编程和功能架构的局限性。
6.1单元测试的三种样式
正如我在本章简介中提到的,单元测试有三种样式:
基于输出的测试
基于状态的测试
基于通信的测试
您可以在一个测试中一起使用一种,两种甚至所有三种样式。 本节通过定义(带有示例)这三种单元测试样式,为整章打下基础。 之后,您将在下面的部分中看到他们如何相互得分。
6.1.1 定义基于输出的样式
单元测试的第一种样式是基于输出的样式,在该样式中,您将输入提供给被测系统(SUT)并检查其产生的输出(图6.1)。 这种类型的单元测试仅适用于不会更改全局或内部状态的代码,因此唯一需要验证的组件是其返回值。
以下清单显示了此类代码的示例以及涵盖该代码的测试。 PriceEngine类接受一系列产品并计算折扣。
public class PriceEngine
{
public decimal CalculateDiscount(params Product[] products)
{
decimal discount = products.Length * 0.01m;
return Math.Min(discount, 0.2m);
}
}
[Fact]
public void Discount_of_two_products()
{
var product1 = new Product("Hand wash");
var product2 = new Product("Shampoo");
var sut = new PriceEngine();
decimal discount = sut.CalculateDiscount(product1, product2);
Assert.Equal(0.02m, discount);
}
PriceEngine将产品数量乘以1%,并将结果上限为20%。 这堂课别无其他。 它不会将产品添加到任何内部收藏中,也不会将其保存在数据库中。 CalculateDiscount()方法的唯一结果是它返回的折扣:输出值(图6.2)。
基于输出的单元测试样式也称为功能。 该名称扎根于函数式编程中,函数式编程是一种强调无副作用代码的编程方法。 我们将在本章后面详细讨论函数式编程和函数式架构。
6.1.2 定义基于状态的样式
基于状态的样式是关于在操作完成之后验证系统状态的方法(图6.3)。 这种测试方式中的状态一词可以指代SUT本身,其协作者之一或进程外依赖项(例如数据库或文件系统)的状态。
这是一个基于状态的测试示例。 Order类允许客户添加新产品。
public class Order
{
private readonly List<Product> _products = new List<Product>();
public IReadOnlyList<Product> Products => _products.ToList();
public void AddProduct(Product product)
{
_products.Add(product);
}
}
[Fact]
public void Adding_a_product_to_an_order()
{
var product = new Product("Hand wash");
var sut = new Order();
sut.AddProduct(product);
Assert.Equal(1, sut.Products.Count);
Assert.Equal(product, sut.Products[0]);
}
该测试在添加完成后验证产品集合。与清单6.1中基于输出的测试示例不同,AddProduct()的结果是对订单状态所做的更改。
6.1.3 定义基于沟通的风格
最后,第三种单元测试是基于通信的测试。这种风格使用模拟来验证被测试系统及其协作者之间的通信(图6.4)。
下面的清单显示了一个基于通信的测试示例。
[Fact]
public void Sending_a_greetings_email()
{
var emailGatewayMock = new Mock<IEmailGateway>();
var sut = new Controller(emailGatewayMock.Object);
sut.GreetUser("[email protected]");
emailGatewayMock.Verify(
x => x.SendGreetingsEmail("[email protected]"),
Times.Once);
}
边栏推荐
- 题目:有一个已经按升序排好序的数组。现输入一个数,要求按原来的规律将它插入数组中。
- Structural mode - adapter mode
- 深度学习领域图像分割FCN(Fully Convolutional Networks for Semantic Segmentation)
- 0 dynamic programming medium leetcode467. The only substring in the surrounding string
- [day02] Introduction to data type conversion, operators and methods
- JS day 2 (variables, variable usage, naming rules, syntax extensions)
- 好用移动APP自动化测试框架哪里找?收藏这份清单就好了!
- Shift right of negative numbers
- IP第十四天笔记
- How can I index the Oracle database field date?
猜你喜欢

iPhone13再降价,其实只是做做样子,消费者都在等iPhone14

F - Pre-order and In-order(Atcoder 255)

管理信息系统期末复习

结构型模式-装饰者模式

Anonymous named pipes, understanding and use of interprocess communication in shared memory

Word/excel has a fixed table size. When filling in the content, the table does not change with the cell content

第六章:云数据库

Yolov4网络详解

Install and configure Debian on a wired network

Final review of management information system
随机推荐
【AtCoder Beginner Contest 260 (A·B·C)】
Explain left value, right value, left value reference and right value reference in detail
有趣的C语言
Hash table questions (Part 2)
Prometheus node exporter common monitoring indicators
数组中的最大值,最小值,冒泡排序
5.component动态组件的展示
Oracle数据库字段date怎么才能走索引?
Ref Hook
Why does genericservlet have two init methods
利用Power Automate,轻松下载Power BI报告中的数据
Effect Hook
JS day 2 (variables, variable usage, naming rules, syntax extensions)
CEPH operation
redux三大核心
Post analysis of Data Analyst
From scratch, C language intensive Lecture 4: array
STL 上头系列——list 容器详解
Digital integrated circuit: MOS tube device chapter (I)
华为入局商用市场:趋势使然,挑战颇多