Util应用框架快速入门(4) - 集成测试开发入门
本文演示Util应用框架开发的项目中如何编写集成测试.
准备
完成 Web Api 快速入门,本文将在之前生成的示例项目上讲解集成测试的开发.
测试概述
自动化测试对于Util应用框架的开发非常重要,它能保证基础功能的稳定性.
对于使用 Util 开发的业务项目,自动化测试不是必须的,但掌握它可能很有用.
如果你使用 Util 开发 Web API,可能会使用 Swagger 进行测试.
将 Swagger 提供给前端人员是合适的,但后端人员使用它却不够省力.
原因很简单,使用 Swagger 测试 API,需要设置一堆参数,这些参数无法保存,每次运行都需要设置.
使用 .Net 自动化测试会更加方便,并且现在开发集成测试的成本很低.
专业测试的分类非常细,下面简要讨论自动化功能测试.
测试分类
这里粗略的对自动化功能测试概括为两类:
单元测试
- 隔绝外部依赖,仅测试自身的某些功能.
- 如果需要访问外部依赖,通过定义抽象接口的方式使用,不能直接引用.
- 在 Util 分层架构中,一般对领域层实体,值对象,领域服务实施单元测试.
集成测试
- 直接访问外部依赖,对关联的所有类型进行测试.
- 在 Util 分层架构中,一般对基础设施层仓储,应用层应用服务和API接口进行集成测试.
测试的好处
修改任何一行业务代码,都有可能影响之前的逻辑.
自动化测试基于对业务功能的预期反应,如果预期未发生变化,但你的代码逻辑出现变化,就能帮你拦截这个错误.
测试的弊端
除了开发自动化测试本身的成本以外,更大的成本在于维护.
每当需求变更,需要删除已经过时的测试,开发新的测试,修改之前的测试以符合当前预期.
测试编写条件
自动化测试的语法非常简单,但并不是掌握了测试语法就能编写出有效的测试.
编写单元测试需要开发人员有一定抽象思维,能够抽象和隔离依赖,还需要了解一些单元测试技巧.
不要在公司全面推行单元测试,容易变成形式主义,仅让团队核心骨干对高价值业务模块编写单元测试.
集成测试则要简单得多,只要懂得测试语法就可以编写.
集成测试由于直接访问外部依赖,运行缓慢,而且任何环节变更都可能导致测试失败,所以不宜大量编写.
你是否需要它?
如果你仅负责编写 Web API ,手头没有现成的UI进行测试,编写集成测试比使用 Swagger 省力.
如果你没有打算持续维护这些测试,不要编写它们,那只会浪费时间.
如果你的团队精力有限,无法维护大量的测试,可以仅对高业务价值的模块编写测试.
测试框架选型
测试框架
- XUnit.Net - 提供基础测试语法.
- XUnit.DependencyInjection - 为测试框架提供依赖注入能力.
模拟框架
- Moq - 为依赖服务接口创建模拟实现.
数据伪造框架
Util集成测试开发入门
单元测试用于测试复杂的业务逻辑,由于快速入门Demo仅包含简单CRUD操作,无法演示单元测试的用法.
下面介绍在Util项目中如何开发集成测试.
运行示例项目
打开示例项目解决方案 Demo.sln,查看 test 子目录,它包含4个测试项目.

生成的测试项目已经将环境配置完成,你可以直接开始编写测试.
Demo.Domain.Tests 是领域层的单元测试项目,如果你不需要编写单元测试,直接删掉它.
其它三个项目用于集成测试,下面分别介绍.
数据访问层集成测试
Demo.Data.SqlServer.Tests 是数据访问层 Sql Server 集成测试项目.
如果支持多种数据库,则每种数据库应包含一个数据访问层集成测试项目.
数据访问层测试的重点是仓储.
打开 StudentRepositoryTest 学生仓储测试类.

在 StudentRepositoryTest 的构造方法中注入了依赖接口 IDemoUnitOfWork 和 IStudentRepository.
Util 代码生成模板默认会创建 TestAddAsync 方法,它用于测试添加实体.
该测试使用伪数据生成框架创建学生实体,并通过仓储保存到数据库.
不宜编写过多的CRUD集成测试,通常保留一两个即可.
它们的作用不是测试逻辑,而是迅速识别开发环境是否通畅.
特别是当你升级框架或类库时,有几个简单的集成测试非常有用.
运行数据访问层集成测试
打开 appsettings.Development.json 配置文件,检查连接字符串是否正确.
{
"ConnectionStrings": {
"connection": "Server=.;Database=Demo.Data.Test;uid=sa;pwd=Pass@word;TrustServerCertificate=true"
}
}
Demo示例的数据访问层测试数据库名为 Demo.Data.Test ,运行测试时, EntityFrameworkCore 会自动创建和删除测试数据库,非常方便.
使用 Visual Studio 运行测试
右键单击 TestAddAsync 方法,弹出菜单选择 运行测试.

弹出 测试资源管理器 窗口,并自动运行测试.

使用 Resharper 运行测试
如果你安装了Resharper, VS中的测试方法会在左侧显示测试图标,如下图所示.

点击 Run 按钮,运行测试.

应用层集成测试
应用层集成测试包含 Demo.Application.Tests 和 Demo.Api.Tests 两个测试项目.
应用服务集成测试
Demo.Application.Tests 侧重于测试应用服务,并且没有Asp.Net Core相关环境干扰.
对于普通项目,大多业务逻辑会写到应用服务中, 所以它是比较理想的测试场所.
如果你不想维护太多测试项目,那么仅保留应用服务集成测试即可.
打开 StudentServiceTest 测试类,代码生成模板默认也创建了一个 TestCreateAsync 测试方法.
/// <summary>
/// 学生服务测试
/// </summary>
public class StudentServiceTest {
/// <summary>
/// 学生服务
/// </summary>
private readonly IStudentService _service;
/// <summary>
/// 测试初始化
/// </summary>
public StudentServiceTest( IStudentService service ) {
_service = service;
}
/// <summary>
/// 测试创建
/// </summary>
[Fact]
public async Task TestCreateAsync() {
//创建
var dto = StudentDtoFakeService.GetStudentDto();
var id = await _service.CreateAsync( dto );
//验证
var result = await _service.GetByIdAsync( id );
Assert.NotNull( result );
Assert.Equal( id, result.Id );
}
}
StudentServiceTest 从构造方法注入了 IStudentService 应用服务接口.
使用伪数据生成框架创建DTO,并调用服务保存数据.
Web Api集成测试
Demo.Api.Tests 用于测试 Web Api控制器,它的测试环境要复杂一些.
打开 StudentControllerTest 测试类.
/// <summary>
/// 学生控制器测试
/// </summary>
public class StudentControllerTest : TestBase {
/// <summary>
/// 输出工具
/// </summary>
private readonly ITestOutputHelper _testOutputHelper;
/// <summary>
/// 测试初始化
/// </summary>
public StudentControllerTest( ITestOutputHelperAccessor testOutputHelperAccessor,IHttpClient client ) : base( client ){
_testOutputHelper = testOutputHelperAccessor.Output;
}
/// <summary>
/// 测试创建
/// </summary>
[Fact]
public async Task TestCreateAsync() {
//服务地址
var url = "/api/student";
//创建实体
var dto = StudentDtoFakeService.GetStudentDto();
var result = await PostAsync<StudentDto>( url, dto );
//验证
Assert.Equal( StateCode.Ok, result.Code );
Assert.NotEmpty( result.Data.Id );
_testOutputHelper.WriteLine( Json.ToJson( result ) );
}
}
Web Api的测试需要发送请求给控制器,并接收响应结果,所以需要一个Http客户端.
StudentControllerTest 构造方法注入 Util Http客户端接口,将将接口传递给 TestBase 基类.
TestBase 进一步封装对 GET, POST ,PUT ,DELETE 操作请求,以简化测试的编写.
默认生成的 TestCreateAsync 方法,使用伪数据生成框架创建DTO, 并使用 Post 请求指定 Url.
Web Api 控制器返回 Util 约定的特定消息.
对于开发 Web Api, 该集成测试能更好的反映与前端的交互.
运行 Web Api集成测试,如下所示.

Util应用框架快速入门(4) - 集成测试开发入门的更多相关文章
- 【python】 web开发入门
进入Web开发 现在你完成了Python忍者训练,准备深入Ptyhon的Web开发,但现在的问题是有很多的框架,从中选择最好的框架非常困难,但从初学者的角度出发,Flask基本Web框架将非常适合We ...
- [译]:Xamarin.Android开发入门——Hello,Android快速上手
返回索引目录 原文链接:Hello, Android_Quickstart. 译文链接:Xamarin.Android开发入门--Hello,Android快速上手 本部分介绍利用Xamarin开发A ...
- 使用 CodeIgniter 框架快速开发 PHP 应用(七)
原文:使用 CodeIgniter 框架快速开发 PHP 应用(七) CodeIgniter 和对象这是玩家章节.它讲述的是 CodeIgniter 的工作原理,也就是揭开CI头上'神秘的面纱'.如果 ...
- 使用 CodeIgniter 框架快速开发 PHP 应用(六)
原文:使用 CodeIgniter 框架快速开发 PHP 应用(六) 简化使用 Session 和安全理论说得够多了! 现在让我们开始写我们自己的应用. 在这一章里,我们将会大致描述一下我们要建立的一 ...
- 使用 CodeIgniter 框架快速开发 PHP 应用(五)
原文:使用 CodeIgniter 框架快速开发 PHP 应用(五) 简化 HTML 页面和表格设计这一章介绍了又一个节约你的时间而且使你的代码更具安全性和逻辑性的领域.第一,我们将会介绍创建视图的各 ...
- 使用 CodeIgniter 框架快速开发 PHP 应用(四)
原文:使用 CodeIgniter 框架快速开发 PHP 应用(四) 使用 CI 简化数据库开发你学习CI 是因为你想要使编程更容易和更有生产力.这一章讲述CI的Active Record类. 如果C ...
- 使用 CodeIgniter 框架快速开发 PHP 应用(二)
原文:使用 CodeIgniter 框架快速开发 PHP 应用(二) 二分钟: 建立一个 CodeIgniter 网站用CI建一个网站很容易. 这一章很短,解释了用CI制作网站时发生了些什么,哪些文件 ...
- 使用 CodeIgniter 框架快速开发 PHP 应用(三)
原文:使用 CodeIgniter 框架快速开发 PHP 应用(三) 分析网站结构既然我们已经安装 CI ,我们开始了解它如何工作.读者已经知道 CI 实现了MVC式样. 通过对目录和文件的内容进行分 ...
- 使用 CodeIgniter 框架快速开发 PHP 应用(一)
原文:使用 CodeIgniter 框架快速开发 PHP 应用(一) 对 CodeIgniter 的介绍大多数PHPer都想写出运行状态良好的应用程序,而且希望尽可能做得简单且不费事.这篇文章是有关 ...
- Python云端系统开发入门——框架基础
Django框架基础 这是我学习北京理工大学嵩天老师的<Python云端系统开发入门>课程的笔记,在此我特别感谢老师的精彩讲解和对我的引导. 1.Django简介与安装 Django是一个 ...
随机推荐
- Web网页音视频通话之基于sipjs功能扩展
在上一篇开发基础上,已经实现了音视频通话.本文是在此基础上继续完成以下内容 关闭/开启音频 开启/关闭视频 屏幕共享 开启/关闭音频 javaScript /** * 静音 */ mute() { i ...
- 【活动回顾】WebRTC服务端工程实践和优化探索
11月7日,即构和上海GDG技术社区联合举办了实时音视频技术云上技术分享专场,来自即构科技和Bilibili的资深技术专家进行了深度分享.大会吸引了众多开发人员交流.观看,并在活动过程中与分享嘉宾进行 ...
- Day09_Java_作业
A:简答题 1.什么是多态,多态的前提是什么? 2.多态中成员(成员变量,成员方法,静态成员方法)的访问特点是什么? 3.多态的好处? 4.多态的弊端是什么,如果我们想访问子类的特有的功能我们应该怎么 ...
- CS144 LAB5~LAB6
CS144 lab5~6 最后两个lab了,虽然很多大佬都说剩下的两个lab比起TCP的实现,"简直太简单了",但是我认为做这两个之前需要补充一些额外的网络知识,不然直接上手去做的 ...
- UE构建基础和实践:四、使用脚本打包
序言 使用UE版本为UE5.20 在实际项目中,我们常常使用自动化脚本来进行构建,它可以增加我们的生产效率,并降低人为操作带来的失误风险. BuildGraph BuildGraph UE官方提供的构 ...
- 若依前后端分离版:增加新的登录接口和新的用户表,用于小程序或者APP获取token,并使用若依的验证方法
相关原创链接直接放这: 基于若依框架springsecurity添加多种用户登录解决方案(springsecurity多用户登录:前端用户.后端用户)_若依多用户表登录_云优的博客-CSDN博客 若依 ...
- rpm安装21c单实例数据库
linux 7.6 使用rpm安装21c单实例数据库 一.基础环境配置 1.1 关闭防火墙 systemctl stop firewalld systemctl disable firewalld s ...
- C# CEFSharp WCF开发桌面程序实现“同一网站多开”
前言 孔乙己显出极高兴的样子,将两个指头的长指甲敲着柜台,点头说:"对呀,对呀!CEFSharp,你用过么?访问同一网址实现多开怎么实现?比如我有3个淘宝店,我想同时登录维护,就像传说中的指 ...
- msfvenom参数简介
-p, –payload < payload> 指定需要使用的payload(攻击荷载).也可以使用自定义payload,几乎是支持全平台的 -l, –list [module_type] ...
- java学习阶段一
扩展名默认没有打开 FIRST APP public class HelloWorld { public static void main (String[] args){ System.out.pr ...