当前位置:网站首页>asp dotnet core 基于 TestServer 做集成测试
asp dotnet core 基于 TestServer 做集成测试
2022-04-21 11:40:00 【lindexi】
我有一个古老的 dotnet core 3.1 的 asp dotnet core 项目,现在我准备将他升级到 dotnet 5 了。但是我不想和博客园一样翻车,因此我需要做一点集成测试的辅助,尽管依然还是翻车了,但是我要学习博客园伟大的精神,将在这个项目里面所做的所有自动化测试项目的方法写下来
在开始从 dotnet core 3.1 升级到 dotnet 5 之前,我先开始准备集成测试。一开始准备的测试是开启主机,然后通过网络调用。然而这个方法一开启我就被拖出去了…… 因为开启主机会占用端口,而刚好我的几个项目都采用了相同的端口
而我开始尝试在配置文件里面指定随机的端口,而此时又有玄学的网络权限,但是我又不知道将谁拖出去
此时小伙伴给我安利了 TestServer 库,通过这个库可以不监听端口,全部都在内存中跑。当然了,访问外部服务就看注入了,没做注入也依然走网络的。只是自己的应用不会去监听端口而已
先新建一个项目,这是一个单元测试项目,用来做集成测试
在 dotnet 里面的套路就是先安装 NuGet 包,然后调用。安装的 NuGet 是 Microsoft.AspNetCore.TestHost 库。这个库一开始需要安装 3.1.10 的版本,在之后项目升级到 dotnet 5 才能使用最新的版本
<
PackageReference
Include=
"Microsoft.AspNetCore.TestHost"
Version=
"3.1.10"
/>
- 1.
在我的单元测试项目里面全部安装的库如下
<
ItemGroup
>
<
PackageReference
Include=
"Microsoft.NET.Test.Sdk"
Version=
"16.8.0"
/>
<
PackageReference
Include=
"MSTest.TestAdapter"
Version=
"2.1.1"
/>
<
PackageReference
Include=
"MSTest.TestFramework"
Version=
"2.1.1"
/>
<
PackageReference
Include=
"coverlet.collector"
Version=
"1.3.0"
/>
<
PackageReference
Include=
"Moq"
Version=
"4.15.1"
/>
<
PackageReference
Include=
"MSTest.TestAdapter"
Version=
"2.1.2"
/>
<
PackageReference
Include=
"MSTest.TestFramework"
Version=
"2.1.2"
/>
<
PackageReference
Include=
"MSTestEnhancer"
Version=
"2.0.1"
/>
<
PackageReference
Include=
"System.Text.Encoding.CodePages"
Version=
"5.0.0"
/>
<
PackageReference
Include=
"Microsoft.AspNetCore.TestHost"
Version=
"3.1.10"
/>
</
ItemGroup
>
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
在使用 TestServer 进行集成测试的时候,其实就是将启动主机的逻辑替换掉,如 ASP.NET Core搭建多层网站架构【12-xUnit单元测试之集成测试】 这篇博客所说的方法,咱来新建一个静态类,用来创建主机和运行
[TestClass]
public static class TestHostBuild
{
public static HttpClient GetTestClient() => _host.GetTestClient();
[AssemblyInitialize]
public static async Task GlobalInitialize(TestContext testContext)
{
IHost host = await CreateAndRun();
_host = host;
}
private static IHost _host;
[AssemblyCleanup]
public static void GlobalCleanup()
{
_host.Dispose();
}
private static Task
<
IHost
> CreateAndRun() => CreateHostBuilder().StartAsync();
public static IHostBuilder CreateHostBuilder() =>
Host.CreateDefaultBuilder()
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup
<
Startup
>();
webBuilder.UseTestServer(); //关键是多了这一行建立TestServer
})
.ConfigureAppConfiguration((hostingContext, config) =>
{
// 进行测试的配置
var appConfigurator = config.ToAppConfigurator();
// 这里使用了 https://github.com/dotnet-campus/dotnetCampus.Configurations 做配置
var apmConfiguration = appConfigurator.Of
<
ApmConfiguration
>();
apmConfiguration.DisableApm = true;
})
// 使用 auto fac 代替默认的 IOC 容器
.UseServiceProviderFactory(new AutofacServiceProviderFactory());
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
上面代码中的 CreateHostBuilder 和 asp dotnet core 项目的 Program.cs 的代码差不多,只是 ConfigureWebHostDefaults 方法更改了
而 ConfigureAppConfiguration 是进行配置,这里进行一些测试项目特意的配置,如禁用了我的 APM 服务。在做集成测试的时候,可以选择开启或关闭 APM 服务,如果你的运维小伙伴不会打你,那么还是开始 APM 比较好。这里的代码使用了 https://github.com/dotnet-campus/dotnetCampus.Configurations 的方法进行配置
在 MSTest 单元测试项目里面,使用 AssemblyInitialize 特性,可以让某个静态方法在单元测试启动的时候运行一次。而使用 AssemblyCleanup 方法可以在单元测试完成之后,无论是否成功都会调用一次
因此在 GlobalInitialize 方法标记 AssemblyInitialize 特性,在这里面创建主机然后运行主机。此时运行的主机不会去监听端口,因此不能通过端口的形式去调用他,而是需要使用 TestServer 提供的扩展方法获取 HttpClient 去访问。也就是通过 TestHostBuild.GetTestClient 拿到的才能访问这个在内存的主机
我对每个控制器都创建一个测试文件,用来进行单元测试
如我的项目里面有一个 StatusOverviewController 控制器,这个控制器用来返回服务的内容,大概逻辑如下
[ApiController]
[Route("[controller]")]
[Route("/")]
public class StatusOverviewController : ControllerBase
{
[HttpGet]
public string Get()
{
// 也许使用 DateTimeOffset 更清真,但这又不是我写的
return DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
新建一个单元测试来测试这个接口的访问
[TestClass]
public class StatusOverviewControllerTest
{
[TestMethod]
public async Task GetTest()
{
using var httpClient = TestHostBuild.GetTestClient();
var result = await httpClient.GetStringAsync("/");
Assert.IsNotNull(result);
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
大概这样就能完成对这个接口的测试了
当然了这是对简单的接口可以这样写,但是对复杂的接口来说,有很多特殊的需求,此时就需要用到 CUnit 库了,通过安装 MSTestEnhancer 这个 NuGet 库就可以添加单元测试辅助库,如下面代码
<
PackageReference
Include=
"MSTestEnhancer"
Version=
"2.0.1"
/>
- 1.
安装之后,就可以写入如下面的逻辑
[TestClass]
public class DemoTest
{
[ContractTestCase]
public void Foo()
{
"当满足 A 条件时,应该发生 A' 事。".Test(() =>
{
// Arrange
// Action
// Assert
});
"当满足 B 条件时,应该发生 B' 事。".Test(() =>
{
// Arrange
// Action
// Assert
});
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
这个 CUnit 在 GitHub 上完全开源,请看 https://github.com/dotnet-campus/CUnit
在准备好了集成测试项目之后,我就开始准备升级到 dotnet 5 了,然而此时发现构建服务器翻车了,如 刚刚我从服务器回滚了 dotnet 5 的环境 博客的内容
终于我通过 如何给 CI CD 服务器搭建上 .NET 5 构建和运行环境 的方法修好了
然而小伙伴告诉我从 dotnet core 3.1 到 dotnet 5 有如下的更改 Breaking changes, version 3.1 to 5.0 - .NET Core
在经过了两天的更新依然失败之后,我强行魔改了代码,上到了 dotet 5 之后,发现了 APM 挂了…… 因 APM 内部使用了原先 dotnet core 3.1 的在 dotnet 5 废弃的接口…… 然后就到了写博客时间了
我搭建了自己的博客 https://blog.lindexi.com/ 欢迎大家访问,里面有很多新的博客。
如果在博客看到有任何不懂的,欢迎交流,我搭建了 dotnet 职业技术学院 欢迎大家加入
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙,不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。
版权声明
本文为[lindexi]所创,转载请带上原文链接,感谢
https://blog.51cto.com/u_11283245/5236424
边栏推荐
猜你喜欢

IIR second order filter in flight control

stm32i2c的解答

星汉未来云原生基础治理平台SchedulX V1.1.0 重磅发布,助力企业降本增效

Packet life cycle in kubernetes -- Part 1

注册新西兰公司流程和需要的资料

Reading material: Information Technology Yearbook

Filter

Kubernetes详解(二)——Kubernetes结构与资源对象

Solution | fast intercom dispatching system: efficient cooperation

Haiwell Cloud Scada Designer 3
随机推荐
JSTL -- JSP standard tag library
Why have major apps launched the old version?
GET 与 POST请求
1. Precision marketing practice Alibaba cloud odpscmd precision marketing data processing
OV代码签名和EV代码签名证书区别
[二叉数]对称二叉树
El expression
打开应用出现 “需要使用新应用一打开此ms-gamingoverlay链接”
LocalDate、LocalDateTime、Date之间的互转
Redis cluster mode
L2-009 抢红包 (25 分)(结构体排序)
【招聘测评题】中的(行测)图形推理题基本逻辑总结(附例题)
分享:Web 网页设计规范
stm32i2c的解答
Conversion between localdate, localdatetime and date
When you open the app, "you need to use a new app to open this MS gamingoverlay link"
开源文化依旧熠熠生辉 —— 在openEuler社区,有技术、有idea,你就是主角
redis面试问题
无线运维的起源与项目建设思考
Filter