对于单元测试、集成测试大部分开发的朋友都懒得去写,因为这要耗费精力去设计去开发,做完项目模块直接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查找注入,

  1. public class Startup
  2. {
  3. // custom host build
  4. public void ConfigureHost(IHostBuilder hostBuilder)
  5. {
  6. hostBuilder
  7. .ConfigureHostConfiguration(builder =>
  8. {
  9. builder.AddJsonFile("appsettings.json", true);
  10. })
  11. .ConfigureWebHostDefaults(builder =>
  12. {
  13. builder.UseStartup<Dx.H5.Service.Startup>();//此处为项目中的startup,不是测试项目中的startup
  14.  
  15. builder.UseTestServer();
  16. builder.ConfigureServices(services =>
  17. {
  18. services.AddSingleton(sp => sp.GetRequiredService<IHost>()
  19. .GetTestClient()
  20. );
  21. });
  22. })
  23. ;
  24. }
  25. // add services need to injection
  26. // ConfigureServices(IServiceCollection services)
  27. // ConfigureServices(IServiceCollection services, HostBuilderContext hostBuilderContext)
  28. // ConfigureServices(HostBuilderContext hostBuilderContext, IServiceCollection services)
  29. public void ConfigureServices(IServiceCollection services)
  30. {
  31. // ready check
  32. //services.AddHostedService<ReadyCheckHostedService>();
  33.  
  34. }
  35.  
  36. public void Configure(ILoggerFactory loggerFactory, ITestOutputHelperAccessor outputHelperAccessor)
  37. {
  38. loggerFactory.AddProvider(new XunitTestOutputLoggerProvider(outputHelperAccessor));
  39. }
  40. }

3.2 NET6 ,测试项目中的Startup需要自己手工创建,NET6 项目取消了Startup那么就需要手工搬移所有的注入,需要注意的是Startup中的ConfigureServices不支持重载,也就是你只能用一个

ConfigureServices方法,见如下示例,还有测试日志的注入,但是在测试项目中使用ILogger<>好像是有问题的,有时日志不打印, 使用

private readonly ITestOutputHelperAccessor _testOutputHelperAccessor; 替代ILogger<>,直接在测试类构造函数中注入就行

  1. public class Startup
  2. {
  3. const string DefaultCorsPolicyName = "Default";
  4. public void ConfigureHost(IHostBuilder hostBuilder) =>
  5. hostBuilder.ConfigureWebHost(webHostBuilder => webHostBuilder
  6. .UseTestServer()
  7. .Configure(Configure)
  8. .UseUrls("http://*:17890","http://*:17880")
  9.  
  10. .ConfigureServices(services =>
  11. {
  12.  
  13. services.AddSingleton(sp => sp.GetRequiredService<IHost>()
  14. .GetTestClient()
  15. );
  16.  
  17. })
  18.  
  19. )
  20. .ConfigureAppConfiguration(lb => lb.AddJsonFile("appsettings.json", false, true));
  21.  
  22. public void ConfigureServices(IServiceCollection services, HostBuilderContext context)
  23. {
  24.  
  25. services.AddControllers();
  26. services.AddEndpointsApiExplorer();
  27. services.AddSwaggerGen();
  28. services.AddHttpClient();
  29.  
  30. }
  31. public void Configure(ILoggerFactory loggerFactory, ITestOutputHelperAccessor accessor) =>
  32. loggerFactory.AddProvider(new XunitTestOutputLoggerProvider(accessor));
  33. ////public void ConfigureHost(IHostBuilder hostBuilder) { }
  34. //public void ConfigureServices(IServiceCollection services)
  35. //{
  36. //}
  37. //public IHostBuilder CreateHostBuilder(AssemblyName assemblyName)
  38. //{
  39. // return new HostBuilder();
  40. //}
  41. private void Configure(IApplicationBuilder app)
  42. {
  43. //if (app.Environment.IsDevelopment())
  44. //{
  45. // app.UseSwagger();
  46. // app.UseSwaggerUI();
  47. //}
  48. app.UseRouting();
  49. app.UseAuthorization();
  50.  
  51. app.UseEndpoints(endpoints =>
  52. {
  53. endpoints
  54. .MapControllers();
  55. endpoints.MapGet("/hb/generatetoken", context =>
  56. {
  57. return context.Response.WriteAsync(GenerateToken(context));
  58. });
  59. });
  60. }
  61. string GenerateToken(HttpContext httpContext)
  62. {
  63. return "dfdfdfdfd";
  64. }
  65. }

  1. public static IEnumerable<object?[]> ReadFile()
  2. {
  3. yield return new object[] { "123"};
  4. yield return new object[] { "456" };
  5. }
  1.  

4.创建测试类测试方法:

需要注意的是api接口测试中url忽略host与端口,默认端口配置请查阅https://github.com/pengweiqhca/Xunit.DependencyInjection文档,UnitTest2中的测试方法是带有数据集合的测试方法,及测试方法是执行多次的,测试方法中的参数数据就是由MemberData(nameof(ReadFile)),其中数据方法ReadFile必须是 public static ReadFile要不然会有报错

  1. using Microsoft.Extensions.Logging;
  2. using Newtonsoft.Json;
  3. using System.Collections.Generic;
  4. using System.Net.Http;
  5. using System.Net.Http.Headers;
  6. using System.Threading.Tasks;
  7. using Xunit;
  8. using Xunit.DependencyInjection;
  9. using Xunit.Extensions.Ordering;
  10. using static WebApiXunit.Controllers.WeatherForecastController;
  11.  
  12. namespace Xunit.WebApiTest
  13. {
  14. [Order(1)]
  15. public class UnitTest1
  16. {
  17. private HttpClient _client;
  18. private ILogger<UnitTest1> _logger;
  19. //private readonly ITestOutputHelperAccessor _testOutputHelperAccessor;
  20. public UnitTest1(
  21. //ITestOutputHelperAccessor testOutputHelperAccessor
  22. ILogger<UnitTest1> logger,
  23. HttpClient client
  24. )
  25. {
  26. _logger = logger;
  27. _client = client;
  28. }
  29. [Order(1)]
  30. [Fact(DisplayName = "1")]
  31. public async Task Test1()
  32. {
  33. var c = new MyClass();
  34. c.Name = "1";
  35. c.Description = "e";
  36. using var request = new HttpRequestMessage(HttpMethod.Post, "WeatherForecast/hb/post/add");
  37. var content = JsonConvert.SerializeObject(c);
  38. request.Content = new StringContent(content);
  39. request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
  40. var resp = await _client.SendAsync(request);
  41. //var resp=await _client.GetAsync("/hb/generatetoken");
  42. _logger.LogInformation("成功");
  43. if (resp.IsSuccessStatusCode)
  44. {
  45.  
  46. var str = await resp.Content.ReadAsStringAsync();
  47. Assert.True(true);
  48. return;
  49. }
  50. Assert.True(false);
  51. }
  52. [Order(2)]
  53. [Fact(DisplayName = "2")]
  54. public async Task Test2()
  55. {
  56. var c = new MyClass();
  57. c.Name = "1";
  58. c.Description = "e";
  59. using var request = new HttpRequestMessage(HttpMethod.Post, "WeatherForecast/hb/post/add");
  60. var content = JsonConvert.SerializeObject(c);
  61. request.Content = new StringContent(content);
  62. request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
  63. var resp = await _client.SendAsync(request);
  64. //var resp=await _client.GetAsync("/hb/generatetoken");
  65.  
  66. //_testOutputHelperAccessor.Output.WriteLine("");
  67. _logger.LogInformation("成功");
  68. if (resp.IsSuccessStatusCode)
  69. {
  70.  
  71. var str = await resp.Content.ReadAsStringAsync();
  72. Assert.True(true);
  73. return;
  74. }
  75. Assert.True(false);
  76. }
  77. }
  78. [Order(2)]
  79. public class UnitTest2
  80. {
  81. private HttpClient _client;
  82. private ILogger<UnitTest2> _logger;
  83. public UnitTest2(
  84.  
  85. ILogger<UnitTest2> logger,
  86. HttpClient client
  87. )
  88. {
  89. _logger = logger;
  90. _client = client;
  91. }
  92.  
  93. [Theory]
  94. [MemberData(nameof(ReadFile))]
  95. public async Task Test2(string name)
  96. {
  97. _logger.LogInformation(name);
  98. Assert.True(true);
  99. }
  100.  
  101. public static IEnumerable<object?[]> ReadFile()
  102. {
  103. yield return new object[] { "123"};
  104. yield return new object[] { "456" };
  105. }
  106. }
  107. }

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")]

  1. using Xunit;
  2. using Xunit.Extensions.Ordering;
  3. [assembly: CollectionBehavior(DisableTestParallelization = true)]
  4. //[assembly: TestFramework("Xunit.Extensions.Ordering.TestFramework", "Xunit.Extensions.Ordering")]
  5. [assembly: TestCaseOrderer("Xunit.Extensions.Ordering.TestCaseOrderer", "Xunit.Extensions.Ordering")]
  6. [assembly: TestCollectionOrderer("Xunit.Extensions.Ordering.CollectionOrderer", "Xunit.Extensions.Ordering")]

6.运行测试项目:

在vs中运行测试项目中右键可以看到运行和调试测试项目运行比较简单,如果在服务器上需要使用dotnet test运行测试,注意配置文件要与服务器的匹配,将项目整体目录拷贝到服务器,cd 到测试项目目录下执行 dotnet test,有多少个接口瞬间测试完毕,而且在项目后续迭代更新的时候,只需要执行以下就可以测试所有的接口。

Net6 Xunit 集成测试的更多相关文章

  1. .net core + xunit 集成测试

    xunit地址:https://github.com/xunit/xunit 一.利用请求来测试接口,主要是测试webapi控制器方法 ①添加xunit项目 ,然后引用我们的主项目,nuget: Mi ...

  2. 如何在ASP.NET 5和XUnit.NET中进行LocalDB集成测试

    今天继续昨天的话题--单元测试,不过是在ASP.NET 5中的单元测试. 在当前的Visual Studio 2015 CTP6中,MSTest是不支持对ASP.NET 5项目进行单元测试的.因而,要 ...

  3. Asp.Net Core 轻松学-利用xUnit进行主机级别的网络集成测试

    前言     在开发 Asp.Net Core 应用程序的过程中,我们常常需要对业务代码编写单元测试,这种方法既快速又有效,利用单元测试做代码覆盖测试,也是非常必要的事情:但是,但我们需要对系统进行集 ...

  4. 体验 ASP.NET Core 集成测试三剑客:xUnit.net、TestServer、EF Core InMemory

    这是昨天解决的一个问题,针对一个 web api 的客户端代理类写集成测试,既要测试 web api,又要测试 web api 客户端. 测试 web api,就要在运行测试时自动启动 web api ...

  5. .netcore持续集成测试篇之开篇简介及Xunit基本使用

    系列目录 为了支持跨平台,微软为.net平台提供了.net core test sdk,这样第三方测试框架诸如Nunit,Xunit等只需要按照sdk提供的api规范进行开发便可以被dotnet cl ...

  6. 使用xunit对asp.net core webapi进行集成测试

    新项目我们采用前后端分离,后端采用asp.net core webapi, 如何对后端代码进行自动化测试呢,有以下几种方案: 1. 单元测试,目前这个方案对我们来说难度很大,抛开时间的问题,单元测试对 ...

  7. .netcore持续集成测试篇之Xunit数据驱动测试一

    系列目录 Nunit里提供了丰富的数据测试功能,虽然Xunit里提供的比较少,但是也能满足很多场景下使用了,如果数据场景非常复杂,Nunit和Xunit都是无法胜任的,有不少测试者选择自己编写一个数据 ...

  8. .netcore持续集成测试篇之Xunit结合netcore内存服务器发送post请求

    系列目录 Web项目中,很多与用户数据交互的请求都是Post请求,想必大家都用过HttpClient构造过post请求,这里并不对HttpClient做详细介绍,只介绍一些常用的功能.并结合AutoF ...

  9. ASP.NET Core 中文文档 第五章 测试(5.2)集成测试

    原文: Integration Testing 作者: Steve Smith 翻译: 王健 校对: 孟帅洋(书缘) 集成测试确保应用程序的组件组装在一起时正常工作. ASP.NET Core支持使用 ...

随机推荐

  1. Cadence 错误合集

    1.原理图DRC出现如下错误"Duplicate Pin Name "GND" found on Packag" 解决方案:原因是元件引脚重复定义,可以进行重新 ...

  2. 《css揭秘》读书笔记

    第一章 引言 css编码技巧 在引言中,作者提到使用em与inherit来实现css代码的简洁与可维护性.但是根据本司机两年的开发经验来看,在实际开发中很少来使用em这个单位.如何用以及何时去使用,还 ...

  3. 检查浏览器支持Webp

    什么是Webp? Webp 是一种支持有损压缩和无损压缩的图片文件格式,派生自图像编码格式 VP8.根据 Google 的测试,无损压缩后的 WebP 比 PNG 文件少了 45% 的文件大小,即使这 ...

  4. ES6-11学习笔记--代理Proxy

    Proxy代理 常用拦截方法 ES5拦截: let obj = {} let newVal = '' Object.defineProperty(obj, 'name', { get() { cons ...

  5. Android:setOnItemClickListener cannot be used with a spinner报错

    错误原因: Spinner对象不支持使用setOnItemClickListener方法监听点击事项 解决方法: 使用setOnItemSelectedListener方法代替setOnItemCli ...

  6. 接口和抽象类的区别(不讲废话,干货满满,JDK1.8最新整理)

    接口和抽象类的区别(不讲废话,干货满满,JDK1.8最新整理) 1.抽象类 以下说辞可能不太准确,但是会让你醍醐灌顶 抽象类是把一些具有共同属性(包括行为)的东西抽象出来,比如: 小狗有身高,体重,颜 ...

  7. OllyDbg---call和ret指令

    call和ret call指令 cal指令是转移到指定的子程序处,后面紧跟的操作数就是给定的地址. 例如,call 401362表示转移到地址401362处,调用401362处的子程序,当子程序调用完 ...

  8. Struts2-从值栈获取list集合数据(三种方式)

    创建User封装数据类 public class User { private String username; private String password; public String getP ...

  9. Go 框架学习之旅 ① 深入解析 net/http 启动服务的层级逻辑

    Web Server. net/http 标准库怎么学. 库函数. 结构定义. 结构函数. 思维导图解析HTTP服务端. 层级逻辑. 创建框架的Server结构. OSI参考模型. TCP/IP五层模 ...

  10. EMC信号完整性落地实测1---走出玄学

    EMC信号完整性落地实测1---走出玄学 无论我们从51单片机,STM32电路,运放,传感器,ADC采集还是可控硅晶闸管等等电源电路跨入到电子工程师的行业,我们通常会长时间处于低频的电子电路设计调试阶 ...