Net6 Xunit 集成测试
对于单元测试、集成测试大部分开发的朋友都懒得去写,因为这要耗费精力去设计去开发,做完项目模块直接postman 调用测试(当然这是一个选择,开发也中经常用到),但是如果测试需要多样化数据,各种场景模拟这样postman测试就暴露了他的局限性,下面我将Net6下没有使用Startup以及NET6以前版本使用Startup的集成测试(单元测试雷同)做一个梳理
1.新建测试项目
2.使用到的类库
Xunti与xunit.runner.visualstudio创建测试项目是自带
Xunit.DependencyInjection 这是一个测试注入的扩展:github地址:https://github.com/pengweiqhca/Xunit.DependencyInjection
Xunit.Extensions.Ordering 这是一个排序执行测试方法的扩展,因为有些方法是需要按照顺序执行,如获取图形验证码-->发送手机验证码-->到获取Token这是一个有序的过程,如果没有按照顺序执行肯定是不对的,github地址:https://github.com/tomaszeman/Xunit.Extensions.Ordering
3.注入
就是将要测试项目的所有注入重新注入测试项目(Program.cs)中和Startup中的所有东东全部注入,NET6中默认取消了Startup类,那么就要手工全部将这些注入再测试项目中添加一次,注入的时候有些是不兼容的做一下小的改动就行,因为https://github.com/pengweiqhca/Xunit.DependencyInjection的注入还是停留在NET5以下版本的,哦对了,还有中间件也是需要在测试项目中添加的,
3.1 NET5 以下,测试项目中的Startup需要自己手工创建,区别在于NET5项目有Startup注入的时候不用手动写很多东西,测试项目直接从项目中的Startup查找注入,
public class Startup
{
// custom host build
public void ConfigureHost(IHostBuilder hostBuilder)
{
hostBuilder
.ConfigureHostConfiguration(builder =>
{
builder.AddJsonFile("appsettings.json", true);
})
.ConfigureWebHostDefaults(builder =>
{
builder.UseStartup<Dx.H5.Service.Startup>();//此处为项目中的startup,不是测试项目中的startup builder.UseTestServer();
builder.ConfigureServices(services =>
{
services.AddSingleton(sp => sp.GetRequiredService<IHost>()
.GetTestClient()
);
});
})
;
}
// add services need to injection
// ConfigureServices(IServiceCollection services)
// ConfigureServices(IServiceCollection services, HostBuilderContext hostBuilderContext)
// ConfigureServices(HostBuilderContext hostBuilderContext, IServiceCollection services)
public void ConfigureServices(IServiceCollection services)
{
// ready check
//services.AddHostedService<ReadyCheckHostedService>(); } public void Configure(ILoggerFactory loggerFactory, ITestOutputHelperAccessor outputHelperAccessor)
{
loggerFactory.AddProvider(new XunitTestOutputLoggerProvider(outputHelperAccessor));
}
}
3.2 NET6 ,测试项目中的Startup需要自己手工创建,NET6 项目取消了Startup那么就需要手工搬移所有的注入,需要注意的是Startup中的ConfigureServices不支持重载,也就是你只能用一个
ConfigureServices方法,见如下示例,还有测试日志的注入,但是在测试项目中使用ILogger<>好像是有问题的,有时日志不打印, 使用
private readonly ITestOutputHelperAccessor _testOutputHelperAccessor; 替代ILogger<>,直接在测试类构造函数中注入就行
public class Startup
{
const string DefaultCorsPolicyName = "Default";
public void ConfigureHost(IHostBuilder hostBuilder) =>
hostBuilder.ConfigureWebHost(webHostBuilder => webHostBuilder
.UseTestServer()
.Configure(Configure)
.UseUrls("http://*:17890","http://*:17880") .ConfigureServices(services =>
{ services.AddSingleton(sp => sp.GetRequiredService<IHost>()
.GetTestClient()
); }) )
.ConfigureAppConfiguration(lb => lb.AddJsonFile("appsettings.json", false, true)); public void ConfigureServices(IServiceCollection services, HostBuilderContext context)
{ services.AddControllers();
services.AddEndpointsApiExplorer();
services.AddSwaggerGen();
services.AddHttpClient(); }
public void Configure(ILoggerFactory loggerFactory, ITestOutputHelperAccessor accessor) =>
loggerFactory.AddProvider(new XunitTestOutputLoggerProvider(accessor));
////public void ConfigureHost(IHostBuilder hostBuilder) { }
//public void ConfigureServices(IServiceCollection services)
//{
//}
//public IHostBuilder CreateHostBuilder(AssemblyName assemblyName)
//{
// return new HostBuilder();
//}
private void Configure(IApplicationBuilder app)
{
//if (app.Environment.IsDevelopment())
//{
// app.UseSwagger();
// app.UseSwaggerUI();
//}
app.UseRouting();
app.UseAuthorization(); app.UseEndpoints(endpoints =>
{
endpoints
.MapControllers();
endpoints.MapGet("/hb/generatetoken", context =>
{
return context.Response.WriteAsync(GenerateToken(context));
});
});
}
string GenerateToken(HttpContext httpContext)
{
return "dfdfdfdfd";
}
}
public static IEnumerable<object?[]> ReadFile()
{
yield return new object[] { "123"};
yield return new object[] { "456" };
}
4.创建测试类测试方法:
需要注意的是api接口测试中url忽略host与端口,默认端口配置请查阅https://github.com/pengweiqhca/Xunit.DependencyInjection文档,UnitTest2中的测试方法是带有数据集合的测试方法,及测试方法是执行多次的,测试方法中的参数数据就是由MemberData(nameof(ReadFile)),其中数据方法ReadFile必须是 public static ReadFile要不然会有报错
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Xunit;
using Xunit.DependencyInjection;
using Xunit.Extensions.Ordering;
using static WebApiXunit.Controllers.WeatherForecastController; namespace Xunit.WebApiTest
{
[Order(1)]
public class UnitTest1
{
private HttpClient _client;
private ILogger<UnitTest1> _logger;
//private readonly ITestOutputHelperAccessor _testOutputHelperAccessor;
public UnitTest1(
//ITestOutputHelperAccessor testOutputHelperAccessor
ILogger<UnitTest1> logger,
HttpClient client
)
{
_logger = logger;
_client = client;
}
[Order(1)]
[Fact(DisplayName = "1")]
public async Task Test1()
{
var c = new MyClass();
c.Name = "1";
c.Description = "e";
using var request = new HttpRequestMessage(HttpMethod.Post, "WeatherForecast/hb/post/add");
var content = JsonConvert.SerializeObject(c);
request.Content = new StringContent(content);
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var resp = await _client.SendAsync(request);
//var resp=await _client.GetAsync("/hb/generatetoken");
_logger.LogInformation("成功");
if (resp.IsSuccessStatusCode)
{ var str = await resp.Content.ReadAsStringAsync();
Assert.True(true);
return;
}
Assert.True(false);
}
[Order(2)]
[Fact(DisplayName = "2")]
public async Task Test2()
{
var c = new MyClass();
c.Name = "1";
c.Description = "e";
using var request = new HttpRequestMessage(HttpMethod.Post, "WeatherForecast/hb/post/add");
var content = JsonConvert.SerializeObject(c);
request.Content = new StringContent(content);
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var resp = await _client.SendAsync(request);
//var resp=await _client.GetAsync("/hb/generatetoken"); //_testOutputHelperAccessor.Output.WriteLine("");
_logger.LogInformation("成功");
if (resp.IsSuccessStatusCode)
{ var str = await resp.Content.ReadAsStringAsync();
Assert.True(true);
return;
}
Assert.True(false);
}
}
[Order(2)]
public class UnitTest2
{
private HttpClient _client;
private ILogger<UnitTest2> _logger;
public UnitTest2( ILogger<UnitTest2> logger,
HttpClient client
)
{
_logger = logger;
_client = client;
} [Theory]
[MemberData(nameof(ReadFile))]
public async Task Test2(string name)
{
_logger.LogInformation(name);
Assert.True(true);
} public static IEnumerable<object?[]> ReadFile()
{
yield return new object[] { "123"};
yield return new object[] { "456" };
}
}
}
5.排序执行测试方法:
使用Xunit.Extensions.Ordering进行排序执行测试方法时:首先在测试项目中新建一个AssemblyInfo.cs加入如下内容,主要没有类名及命名空间,其中[assembly: TestFramework("Xunit.Extensions.Ordering.TestFramework", "Xunit.Extensions.Ordering")]是一个按照集合进行排序的使用,但是他与已有xunit assembly冲突,暂时么有找到解决方法,所以该排序功能暂时不支持,类中的[Order(2)]为第一优先级排序顺序,方法中的[Order(2)]即在类的顺序下再排序
using Xunit;
using Xunit.Extensions.Ordering;
[assembly: CollectionBehavior(DisableTestParallelization = true)]
//[assembly: TestFramework("Xunit.Extensions.Ordering.TestFramework", "Xunit.Extensions.Ordering")]
[assembly: TestCaseOrderer("Xunit.Extensions.Ordering.TestCaseOrderer", "Xunit.Extensions.Ordering")]
[assembly: TestCollectionOrderer("Xunit.Extensions.Ordering.CollectionOrderer", "Xunit.Extensions.Ordering")]
using Xunit;
using Xunit.Extensions.Ordering;
[assembly: CollectionBehavior(DisableTestParallelization = true)]
//[assembly: TestFramework("Xunit.Extensions.Ordering.TestFramework", "Xunit.Extensions.Ordering")]
[assembly: TestCaseOrderer("Xunit.Extensions.Ordering.TestCaseOrderer", "Xunit.Extensions.Ordering")]
[assembly: TestCollectionOrderer("Xunit.Extensions.Ordering.CollectionOrderer", "Xunit.Extensions.Ordering")]
6.运行测试项目:
在vs中运行测试项目中右键可以看到运行和调试测试项目运行比较简单,如果在服务器上需要使用dotnet test运行测试,注意配置文件要与服务器的匹配,将项目整体目录拷贝到服务器,cd 到测试项目目录下执行 dotnet test,有多少个接口瞬间测试完毕,而且在项目后续迭代更新的时候,只需要执行以下就可以测试所有的接口。
Net6 Xunit 集成测试的更多相关文章
- .net core + xunit 集成测试
xunit地址:https://github.com/xunit/xunit 一.利用请求来测试接口,主要是测试webapi控制器方法 ①添加xunit项目 ,然后引用我们的主项目,nuget: Mi ...
- 如何在ASP.NET 5和XUnit.NET中进行LocalDB集成测试
今天继续昨天的话题--单元测试,不过是在ASP.NET 5中的单元测试. 在当前的Visual Studio 2015 CTP6中,MSTest是不支持对ASP.NET 5项目进行单元测试的.因而,要 ...
- Asp.Net Core 轻松学-利用xUnit进行主机级别的网络集成测试
前言 在开发 Asp.Net Core 应用程序的过程中,我们常常需要对业务代码编写单元测试,这种方法既快速又有效,利用单元测试做代码覆盖测试,也是非常必要的事情:但是,但我们需要对系统进行集 ...
- 体验 ASP.NET Core 集成测试三剑客:xUnit.net、TestServer、EF Core InMemory
这是昨天解决的一个问题,针对一个 web api 的客户端代理类写集成测试,既要测试 web api,又要测试 web api 客户端. 测试 web api,就要在运行测试时自动启动 web api ...
- .netcore持续集成测试篇之开篇简介及Xunit基本使用
系列目录 为了支持跨平台,微软为.net平台提供了.net core test sdk,这样第三方测试框架诸如Nunit,Xunit等只需要按照sdk提供的api规范进行开发便可以被dotnet cl ...
- 使用xunit对asp.net core webapi进行集成测试
新项目我们采用前后端分离,后端采用asp.net core webapi, 如何对后端代码进行自动化测试呢,有以下几种方案: 1. 单元测试,目前这个方案对我们来说难度很大,抛开时间的问题,单元测试对 ...
- .netcore持续集成测试篇之Xunit数据驱动测试一
系列目录 Nunit里提供了丰富的数据测试功能,虽然Xunit里提供的比较少,但是也能满足很多场景下使用了,如果数据场景非常复杂,Nunit和Xunit都是无法胜任的,有不少测试者选择自己编写一个数据 ...
- .netcore持续集成测试篇之Xunit结合netcore内存服务器发送post请求
系列目录 Web项目中,很多与用户数据交互的请求都是Post请求,想必大家都用过HttpClient构造过post请求,这里并不对HttpClient做详细介绍,只介绍一些常用的功能.并结合AutoF ...
- ASP.NET Core 中文文档 第五章 测试(5.2)集成测试
原文: Integration Testing 作者: Steve Smith 翻译: 王健 校对: 孟帅洋(书缘) 集成测试确保应用程序的组件组装在一起时正常工作. ASP.NET Core支持使用 ...
随机推荐
- TL431常用电路整理
熟悉电路制作的人大多对TL431并不陌生.由于TL431的动态抗阻的特性,其经常在电路设计当中被用于替代稳压二极管.不仅如此,TL431的开态响应速度快输出噪音低,并且价格低廉.因此受到电源工程师和初 ...
- Vue的computed(计算属性)使用实例之TodoList
最近倒腾了一会vue,有点迷惑其中methods与computed这两个属性的区别,所以试着写了TodoList这个demo,(好土掩面逃~); 1. methods methods类似react中组 ...
- 检查浏览器支持Webp
什么是Webp? Webp 是一种支持有损压缩和无损压缩的图片文件格式,派生自图像编码格式 VP8.根据 Google 的测试,无损压缩后的 WebP 比 PNG 文件少了 45% 的文件大小,即使这 ...
- 使用 Vuex + Vue.js 构建单页应用【新篇】
使用 Vuex + Vue.js 构建单页应用[新篇] 在去年的七月六号的时候,发布了一篇 使用 Vuex + Vue.js 构建单页应用 的文章,文章主要是介绍 vuex 的基本使用方法,发现对大部 ...
- 一个抽取百度定位的教程(下载百度地图Demo+配置+抽取)
效果展示 已经下载Demo的可以直接到第五步,已经配置好的并可以运行的可以直接到第七步. 1.在浏览器搜索 " 百度定位API ",点击下面这个链接 2.翻到最下面找到并点击 &q ...
- MFC软件国际化的几个问题及其解决方案
作者:马健 邮箱:stronghorse_mj@hotmail.com主页:https://www.cnblogs.com/stronghorse/ 以前我以为PDG相关软件只会在国内流行,所以发行简 ...
- CommonsCollection6反序列化链学习
CommonsCollection6 1.前置知识 1.1.HashSet HashSet 基于 HashMap 来实现的,是一个不允许有重复元素的集合.继承了序列化和集合 构造函数参数为空的话创建一 ...
- 使用Socket实现HttpServer(三)
使用Socket实现HttpServer(三) 这一章继续对我们的服务器进行优化,引入 NIO package com.fengsir.network.step4; import java.io.IO ...
- PyQt5 基本语法(五)
目录 2. 输入控件(二) 2.2 步长调节 2.2.1 QAbstractSpinBox 2.2.1.1 描述 2.2.1.2 功能作用 2.2.1.2.1 使用 2.2.1.2.2 主要功能 2. ...
- 微信小程序,制作属于自己的Icon图标
前言 最近在接手一个微信小程序,发现里面的图标都是使用的image组件,看起来非常别扭,加载也不太顺畅. 就想着看看微信有没有类似自带的图标库可以使用. 有是有,就是太少了,翻来翻去好像也就 8 种, ...