.NET 6控制器Action方法测试:正确传递路径与查询参数
正确传递.NET 6控制器HttpGet的路径与查询参数
问题背景
你需要测试的HttpGet Action包含路径参数endDate、client,以及查询参数creationDate、字符串数组portfolios和可选布尔参数includeGeneric。当前测试代码因参数传递方式错误无法运行,以下是修正方案:
原Action方法代码
[HttpGet("Date/{endDate}/client/{client}")] public IActionResult GetClient( DateTime endDate, string client, [FromQuery] DateTime creationDate, [FromQuery] string[] portfolios, [FromQuery] bool includeGeneric = false) { var result = new List<Portfolio>(); var param = new PortfoliosParams(portfolios, new[] { client }, endDate, creationDate); var portfolios = this.repository.GetPortfolios(param); result.AddRange(portfolios); var portfolioRepository = this.portfolioRepository.GetPortfolioRepository(param); result.AddRange(portfolioRepository); var params = new PortfoliosParams(portfolios, new[] { Helpers.ClientName }, endDate, creationDate); var genericPortfolios = this.repository.GetPortfolios(params); result.AddRange(genericPortfolios); var genericPortfoliosRepository = this.portfolioRepository.GetPortfolioRepository(params); result.AddRange(genericPortfoliosRepository); return this.Ok(result); }
原测试代码的核心问题
- 路径占位符
{endDate}、{client}未被实际值替换,直接作为静态字符串传递 - 查询参数
creationDate、portfolios未拼接到URL的查询字符串中 GetAsync方法参数传递逻辑错误,该方法不支持自动将多参数拼接为URL- 断言逻辑错误:
GetAsync返回的是HttpResponseMessage对象,无法直接断言等于数值3
修正后的测试代码
[Test] public async Task GetPortfolios() { var clientName = "TEST"; var creationDate = new DateTime(2023, 5, 1); var endDate = new DateTime(2024, 1, 1); var portfolios = new[] { "TEST1", "TEST2", "TEST3" }; var server = TestHelpers.CreateTestServer(); var httpClient = server.CreateClient(); // 1. 替换路径参数,DateTime使用ISO 8601格式确保路由绑定成功 var basePath = $"api/Portfolios/Date/{endDate:yyyy-MM-dd}/client/{clientName}"; // 2. 构建查询字符串,自动处理URL编码 var queryBuilder = new QueryString(); queryBuilder = queryBuilder.Add("creationDate", creationDate.ToString("yyyy-MM-dd")); // 数组参数采用重复key的形式(ASP.NET Core默认支持该绑定方式) foreach (var portfolio in portfolios) { queryBuilder = queryBuilder.Add("portfolios", portfolio); } // 可选参数includeGeneric默认是false,若需传true则取消下方注释 // queryBuilder = queryBuilder.Add("includeGeneric", "true"); // 3. 拼接完整请求URL var requestUrl = basePath + queryBuilder; // 4. 发送请求并验证响应状态 var response = await httpClient.GetAsync(requestUrl); response.EnsureSuccessStatusCode(); // 5. 读取响应内容并执行断言 var result = await response.Content.ReadFromJsonAsync<List<Portfolio>>(); Assert.That(result.Count, Is.EqualTo(3)); } public static class TestHelpers { private static WebApplicationFactory<Program> testServer; public static WebApplicationFactory<Program> CreateTestServer() { if (testServer != null) { return testServer; } return testServer = new WebApplicationFactory<Program>() .WithWebHostBuilder(builder => builder .UseContentRoot(Directory.GetCurrentDirectory())); } }
关键注意事项
- 路径参数处理:必须直接替换URL中的占位符,DateTime需使用控制器可正确绑定的格式(推荐ISO 8601)
- 查询数组参数:ASP.NET Core默认支持
portfolios=TEST1&portfolios=TEST2的重复key形式,无需额外配置 - 查询字符串拼接:使用
QueryString类可避免手动拼接时的URL编码错误 - 响应断言:需先确保请求成功,再将响应内容反序列化为实体类后,针对实体属性执行断言
内容的提问来源于stack exchange,提问作者Garry A
相关产品推荐
相关产品推荐

