本文演示Util应用框架开发的项目中如何编写集成测试.

准备

完成 Web Api 快速入门,本文将在之前生成的示例项目上讲解集成测试的开发.

测试概述

自动化测试对于Util应用框架的开发非常重要,它能保证基础功能的稳定性.

对于使用 Util 开发的业务项目,自动化测试不是必须的,但掌握它可能很有用.

如果你使用 Util 开发 Web API,可能会使用 Swagger 进行测试.

将 Swagger 提供给前端人员是合适的,但后端人员使用它却不够省力.

原因很简单,使用 Swagger 测试 API,需要设置一堆参数,这些参数无法保存,每次运行都需要设置.

使用 .Net 自动化测试会更加方便,并且现在开发集成测试的成本很低.

专业测试的分类非常细,下面简要讨论自动化功能测试.

测试分类

这里粗略的对自动化功能测试概括为两类:

  • 单元测试

    • 隔绝外部依赖,仅测试自身的某些功能.
    • 如果需要访问外部依赖,通过定义抽象接口的方式使用,不能直接引用.
    • 在 Util 分层架构中,一般对领域层实体,值对象,领域服务实施单元测试.
  • 集成测试

    • 直接访问外部依赖,对关联的所有类型进行测试.
    • 在 Util 分层架构中,一般对基础设施层仓储,应用层应用服务和API接口进行集成测试.

测试的好处

修改任何一行业务代码,都有可能影响之前的逻辑.

自动化测试基于对业务功能的预期反应,如果预期未发生变化,但你的代码逻辑出现变化,就能帮你拦截这个错误.

测试的弊端

  • 除了开发自动化测试本身的成本以外,更大的成本在于维护.

  • 每当需求变更,需要删除已经过时的测试,开发新的测试,修改之前的测试以符合当前预期.

测试编写条件

自动化测试的语法非常简单,但并不是掌握了测试语法就能编写出有效的测试.

编写单元测试需要开发人员有一定抽象思维,能够抽象和隔离依赖,还需要了解一些单元测试技巧.

不要在公司全面推行单元测试,容易变成形式主义,仅让团队核心骨干对高价值业务模块编写单元测试.

集成测试则要简单得多,只要懂得测试语法就可以编写.

集成测试由于直接访问外部依赖,运行缓慢,而且任何环节变更都可能导致测试失败,所以不宜大量编写.

你是否需要它?

  • 如果你仅负责编写 Web API ,手头没有现成的UI进行测试,编写集成测试比使用 Swagger 省力.

  • 如果你没有打算持续维护这些测试,不要编写它们,那只会浪费时间.

  • 如果你的团队精力有限,无法维护大量的测试,可以仅对高业务价值的模块编写测试.

测试框架选型

  • 测试框架

  • 模拟框架

    • 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.TestsDemo.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) - 集成测试开发入门的更多相关文章

  1. 【python】 web开发入门

    进入Web开发 现在你完成了Python忍者训练,准备深入Ptyhon的Web开发,但现在的问题是有很多的框架,从中选择最好的框架非常困难,但从初学者的角度出发,Flask基本Web框架将非常适合We ...

  2. [译]:Xamarin.Android开发入门——Hello,Android快速上手

    返回索引目录 原文链接:Hello, Android_Quickstart. 译文链接:Xamarin.Android开发入门--Hello,Android快速上手 本部分介绍利用Xamarin开发A ...

  3. 使用 CodeIgniter 框架快速开发 PHP 应用(七)

    原文:使用 CodeIgniter 框架快速开发 PHP 应用(七) CodeIgniter 和对象这是玩家章节.它讲述的是 CodeIgniter 的工作原理,也就是揭开CI头上'神秘的面纱'.如果 ...

  4. 使用 CodeIgniter 框架快速开发 PHP 应用(六)

    原文:使用 CodeIgniter 框架快速开发 PHP 应用(六) 简化使用 Session 和安全理论说得够多了! 现在让我们开始写我们自己的应用. 在这一章里,我们将会大致描述一下我们要建立的一 ...

  5. 使用 CodeIgniter 框架快速开发 PHP 应用(五)

    原文:使用 CodeIgniter 框架快速开发 PHP 应用(五) 简化 HTML 页面和表格设计这一章介绍了又一个节约你的时间而且使你的代码更具安全性和逻辑性的领域.第一,我们将会介绍创建视图的各 ...

  6. 使用 CodeIgniter 框架快速开发 PHP 应用(四)

    原文:使用 CodeIgniter 框架快速开发 PHP 应用(四) 使用 CI 简化数据库开发你学习CI 是因为你想要使编程更容易和更有生产力.这一章讲述CI的Active Record类. 如果C ...

  7. 使用 CodeIgniter 框架快速开发 PHP 应用(二)

    原文:使用 CodeIgniter 框架快速开发 PHP 应用(二) 二分钟: 建立一个 CodeIgniter 网站用CI建一个网站很容易. 这一章很短,解释了用CI制作网站时发生了些什么,哪些文件 ...

  8. 使用 CodeIgniter 框架快速开发 PHP 应用(三)

    原文:使用 CodeIgniter 框架快速开发 PHP 应用(三) 分析网站结构既然我们已经安装 CI ,我们开始了解它如何工作.读者已经知道 CI 实现了MVC式样. 通过对目录和文件的内容进行分 ...

  9. 使用 CodeIgniter 框架快速开发 PHP 应用(一)

    原文:使用 CodeIgniter 框架快速开发 PHP 应用(一) 对 CodeIgniter 的介绍大多数PHPer都想写出运行状态良好的应用程序,而且希望尽可能做得简单且不费事.这篇文章是有关 ...

  10. Python云端系统开发入门——框架基础

    Django框架基础 这是我学习北京理工大学嵩天老师的<Python云端系统开发入门>课程的笔记,在此我特别感谢老师的精彩讲解和对我的引导. 1.Django简介与安装 Django是一个 ...

随机推荐

  1. 大数据面试题集锦-Hadoop面试题(四)-YARN

    你准备好面试了吗?这里有一些面试中可能会问到的问题以及相对应的答案.如果你需要更多的面试经验和面试题,关注一下"张飞的猪大数据分享"吧,公众号会不定时的分享相关的知识和资料. 目录 ...

  2. Lifecycle解决了什么问题,以及它的基本用法

    1.为何要引入Lifecycle? 我首先来举个大家都比较常见的例子:我们在android开发的时候,经常需要在页面的onCreate()方法中对组件进行初始化,在onPause()方法中停止组件,而 ...

  3. sensor binning信号及信噪比

    Signal是简单的增加,Noise是以均方根形式增加 例如: 2*2的binning模式中,signal增加4倍,noise增加 4 \sqrt4 4 ​倍,so SNR增加2倍. sony sen ...

  4. Linux reset子系统

    文章代码分析基于linux-5.19.13,架构基于aarch64(ARM64). 1. 前言 复杂IC内部有很多具有独立功能的硬件模块,例如CPU cores.GPU cores.USB控制器.MM ...

  5. Mediabox:年度最佳音视频开发工具

    "2023稀土开发者大会"落下帷幕,由稀土掘金社区评选的的掘金技术引力榜重磅出炉,共有22个优秀实践案例上榜,涵盖对技术行业发展有特别贡献的人物.开发工具.开源项目.技术团队和技术 ...

  6. Centos7制作本地yum仓库,共享给局域网其他设备

    环境准备: 准备好安装好Centos7的虚机A(服务端)和虚机B(客户端) 配置两台虚机网络使其互通,关闭selinux和firewalld等限制 下载完整的ISO镜像(CentOS-7-x86_64 ...

  7. 获取Rtx用户状态方法

    背景:企业OA系统需要与Rtx集成,且高权限身份用户需要获取符合某一条下的所有员工rtx状态... 方案:以此背景,基于rtx sdk做二次开发, 1.后台调用RootObj.QueryUserSta ...

  8. WebStorm: 配置React中useState自动补齐功能

    配置如下 模板文本如下所示 const [$STATE$, $SET_STATE$] = useState($INITAL_STATE$) 编辑变量 SET_STATE文本如下所示 concat(&q ...

  9. opencv-python中 boundingRect(cnt)以及cv2.rectangle用法

    矩形边框(Bounding Rectangle)是说,用一个最小的矩形,把找到的形状包起来.还有一个带旋转的矩形,面积会更小,效果见下图 首先介绍下cv2.boundingRect(img)这个函数 ...

  10. 开源元数据管理平台Datahub最新版本0.10.5——安装部署手册(附离线安装包)

    大家好,我是独孤风. 开源元数据管理平台Datahub近期得到了飞速的发展.已经更新到了0.10.5的版本,来咨询我的小伙伴也越来越多,特别是安装过程有很多问题.本文经过和群里大伙伴的共同讨论,总结出 ...