<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
對於單元測試、整合測試大部分開發的朋友都懶得去寫,因為這要耗費精力去設計去開發,做完專案模組直接postman 呼叫測試(當然這是一個選擇,開發也中經常用到),但是如果測試需要多樣化資料,各種場景模擬這樣postman測試就暴露了他的侷限性,下面我將Net6下沒有使用Startup以及NET6以前版本使用Startup的整合測試(單元測試雷同)做一個梳理
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
就是將要測試專案的所有注入重新注入測試專案(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" }; }
需要注意的是api介面測試中url忽略host與埠,預設埠設定請查閱https://github.com/pengweiqhca/Xunit.DependencyInjection檔案,UnitTest2中的測試方法是帶有資料集合的測試方法,及測試方法是執行多次的,測試方法中的引數資料就是由MemberData(nameof(ReadFile)),其中資料方法ReadFile必須是 public staticReadFile要不然會有報錯
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" }; } } }
使用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")]
在vs中執行測試專案中右鍵可以看到執行和偵錯測試專案執行比較簡單,如果在伺服器上需要使用dotnet test執行測試,注意組態檔要與伺服器的匹配,將專案整體目錄拷貝到伺服器,cd 到測試專案目錄下執行 dotnet test,有多少個介面瞬間測試完畢,而且在專案後續迭代更新的時候,只需要執行以下就可以測試所有的介面。
到此這篇關於Net6 Xunit 整合測試的文章就介紹到這了,更多相關Net6 Xunit 整合測試內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45