如何对返回含匿名类型OkNegotiatedContentResult的IHttpActionResult做单元测试
问题根因
你返回的Ok结果里封装的是包含Data和Total两个属性的匿名类型,而非直接返回List<ViewModelName>,所以强制转换为OkNegotiatedContentResult<List<ViewModelName>>必然匹配失败,得到null。
解决方案
方案1:使用dynamic读取内容(无需修改现有接口代码)
直接通过dynamic类型动态读取返回内容,代码示例如下:
[TestMethod] public void TestMethodName() { var result = controller.MethodName(); // 转为dynamic后直接读取Content属性 dynamic okResult = result as dynamic; IEnumerable<ViewModelName> data = okResult.Content.Data; int total = okResult.Content.Total; // 后续添加你的断言逻辑即可,示例: Assert.IsNotNull(data); Assert.IsTrue(total >= 0); }
注意:如果测试项目与Web API项目为不同程序集,需要在Web API项目的
AssemblyInfo.cs中添加配置,允许测试项目访问内部匿名类型:[assembly: InternalsVisibleTo("你的测试项目的程序集名称")]
方案2:定义强类型返回类(更推荐,类型安全、可维护性高)
优先避免使用匿名类型作为接口返回值,专门定义通用的强类型返回类,后续无论接口开发还是单元测试都可以直接做类型匹配。
第一步:定义通用返回类
public class PagedResult<T> { public IEnumerable<T> Data { get; set; } public int Total { get; set; } }
第二步:修改控制器返回逻辑
public IHttpActionResult MethodName() { // 原有业务逻辑不变 return Ok(new PagedResult<ViewModelName> { Data = result, Total = result.Any() ? result.First().TotalCount : 0 }); }
第三步:测试代码安全转换
[TestMethod] public void TestMethodName() { var result = controller.MethodName(); var contentResult = result as OkNegotiatedContentResult<PagedResult<ViewModelName>>; // 先断言转换成功 Assert.IsNotNull(contentResult); var returnData = contentResult.Content.Data; int returnTotal = contentResult.Content.Total; // 后续添加业务断言即可 }
内容的提问来源于stack exchange,提问作者Jimesh
相关产品推荐
相关产品推荐

