- A+
前言
在AspnetCore生态系统中,我们测试项目一般使用Microsoft.AspNetCore.TestHost
的TestServer
到.NET6后提供的Microsoft.AspNetCore.Mvc.Testing
的WebApplicationFactory
,后者是前者的封装,专门用于测试 ASP.NET Core 应用程序。它简化了创建和配置测试服务器的过程。而Alba
也是基于前者的封装,同样提供了一些好用的测试体验
使用 Alba 进行集成测试
以下我们来体验一下TA的一些好用的测试体验:
首先,你需要在项目中安装 Alba 包。可以使用以下命令通过 NuGet 包管理器进行安装:
dotnet add package Alba
为了演示 Alba 的使用,我们首先创建一个简单的 ASP.NET Core 应用程序。这个应用程序包含一个返回 "Hello, World!" 的 MinimalApi请求。
var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.MapGet("/", () => "Hello, World!"); app.Run(); namespace TestCase { public partial class Program { } //定义一个入口点用于测试 }
接下来,我们使用 Alba 创建一个基于xUnit
的集成测试,测试上述应用程序。
using Alba; public class IntegrationTests { [Fact] public async Task Get_Home_Returns_HelloWorld() { using var host = await AlbaHost.For<TestCase.Program>(builder => { // 这里可以配置服务和中间件 }); await host.Scenario(scenario => { scenario.Get.Url("/"); scenario.StatusCodeShouldBeOk(); scenario.ContentShouldBe("Hello, World!"); }); } }
AlbaHost有一个方法Scenario(x=>{})
用于定义测试场景,比如上面的测试用例,场景使用GET请求起始页并断言是否返回200
,以及返回的文本是否是Hello, World!
对于内置场景没有支撑到位的断言,我们也可以使用参数接收IScenarioResult
自行断言:
var myScenario = await _host.Scenario(_ => { _.Get.Url("/"); }); Assert.Equal("true", myScenario.ReadAsText()); Assert.Equal(200, myScenario.Context.Response.StatusCode);
对于POST等方式提供链式的语法风格,Alba会自动帮我们序列化:
using Alba; public class IntegrationTests { [Fact] public async Task Post_Data_Returns_Correct_Response() { using var host = await AlbaHost.For<TestCase.Program>(); await host.Scenario(scenario => { scenario.Post.Json(new { Name = "Test" }).ToUrl("/data"); scenario.StatusCodeShouldBeOk(); scenario.ContentShouldBe("Received: Test"); }); } }
对于Xml
和FormData
的POST,Scenario
也是提供支持的,例如:
//xml scenario.Post.Xml(new Input {Name = "vipwan", Age = 18}); //form public async Task write_form_data(IAlbaHost system) { var form1 = new Dictionary<string, string> { ["a"] = "what?", ["b"] = "now?", ["c"] = "really?" }; await system.Scenario(_ => { // This writes the dictionary values to the HTTP // request as form data, and sets the content-length // header as well as setting the content-type // header to application/x-www-form-urlencoded _.WriteFormData(form1); }); }
当然除了传参的时候自动序列化,Alba对响应的返回也提供了反序列化支持:
public async Task read_json(IAlbaHost host) { var result = await host.Scenario(_ => { _.Get.Url("/output"); }); var output = result.ReadAsJsonAsync<Output>(); } //或者 public async Task read_json_shorthand(IAlbaHost host) { var output = await host.GetAsJson<Output>("/output"); }
如果需要测试需要鉴权认证的请求,Alba也帮我们做了封装.我们只需要实例化AuthenticationStub
或者JwtSecurityStub
亦或者实现OpenConnectExtension
,然后在实例化AlbaHost时传入即可!
var securityStub = new AuthenticationStub() .With("foo", "bar")//演示添加的claim .With(JwtRegisteredClaimNames.Email, "vipwan@co.ltd")//演示添加的claim .WithName("vipwan"); myHost = await AlbaHost.For<WebAppSecuredWithJwt.Program>(securityStub);
如上面的代码只要我们使用myHost
实例创建的任何场景将自动附加相应的认证信息:
//当请求需要认证的时候也可以通过测试 app.MapGet("/", () => "Hello, World!").RequireAuthorization();
对于请求Alba还支持请求的AOP,比如请求前后我们需要对HttpContext
做一些改动:
public void sample_usage(AlbaHost system) { // Synchronously system.BeforeEach(context => { // Modify the HttpContext immediately before each // Scenario()/HTTP request is executed context.Request.Headers.Add("trace", "something"); }); system.AfterEach(context => { // perform an action immediately after the scenario/HTTP request // is executed }); // Asynchronously system.BeforeEachAsync(context => { // do something asynchronous here return Task.CompletedTask; }); system.AfterEachAsync(context => { // do something asynchronous here return Task.CompletedTask; }); }
这里介绍了一些Alba的特性和使用方式,当然还不完善,如果你对这个库感兴趣可以点击链接查看官方的文档
总结
Alba 是一个比较简单的测试库,提供了我们对Web项目测试常用的场景封装,下图是AlbaHost
简单架构:
Alba 提供了多种便捷的测试方式,使得编写和执行集成测试变得更加简单和高效。无论是基本的 HTTP 请求测试、带有依赖注入的请求测试、POST 请求测试、带有认证的请求测试,还是复杂的请求和响应测试,Alba 都能很好地满足你的需求。通过使用 Alba,你可以更轻松地编写可靠的集成测试,确保你的应用程序在各种情况下都能正常工作。