如何在Xunit测试中获取Web Api返回的Problem类型错误消息
解决方案
实现原理
ASP.NET Core 中ControllerBase.Problem()方法返回的是符合RFC7807规范的标准化错误响应,对应类型为Microsoft.AspNetCore.Mvc.ProblemDetails,你只需要将测试得到的响应内容反序列化为该类型,即可读取错误详情字段。
具体实现步骤
- 先确保测试项目引用了
Microsoft.AspNetCore.Mvc.Core包,包含ProblemDetails类型定义 - 修改测试用例,在拿到响应后反序列化内容并断言:
using Microsoft.AspNetCore.Mvc; using System.Text.Json; [Fact] public async Task AddCampaign_ReturnBadRequestWhenStartDateIsGreaterThanEndDate() { var client = _factory.CreateClient(); string title = string.Format("Test Add Campaign {0}", Guid.NewGuid()); var campaignAddDto = new CampaignDTORequest { Title = title, StartDate = new DateTime(2021, 6, 7), EndDate = new DateTime(2021, 6, 6) }; var encodedContent = new StringContent(JsonConvert.SerializeObject(campaignAddDto), Encoding.UTF8, "application/json"); var response = await client.PostAsync("/api/Campaign/add", encodedContent); // 读取响应内容并反序列化 var responseContent = await response.Content.ReadAsStringAsync(); var problemDetails = JsonSerializer.Deserialize<ProblemDetails>(responseContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true // 忽略JSON属性大小写匹配 }); Assert.False(response.IsSuccessStatusCode); Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); // 断言错误消息内容 Assert.Equal("你预期的错误提示文本", problemDetails.Detail); // 也可根据需求断言Problem的其他字段,比如Title、Status等 }
如果你项目用的是Newtonsoft.Json做序列化,直接用JsonConvert.DeserializeObject<ProblemDetails>(responseContent)即可,不需要额外配置大小写忽略。
特殊场景说明
如果你的日期校验是通过模型属性的DataAnnotation或者FluentValidation实现,走ASP.NET Core自动模型验证流程的话,返回的是ValidationProblemDetails类型(继承自ProblemDetails),包含字段级别的错误列表,反序列化时改为对应类型即可读取字段错误:
var validationProblem = JsonSerializer.Deserialize<ValidationProblemDetails>(responseContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); // 断言StartDate字段的错误信息 Assert.Contains("开始日期不能晚于结束日期", validationProblem.Errors[nameof(CampaignDTORequest.StartDate)].First());
内容的提问来源于stack exchange,提问作者Steve
相关产品推荐
相关产品推荐

