【问题标题】:How to unit-test action with return type ActionResult<T>?如何使用返回类型 ActionResult<T> 对操作进行单元测试?
【发布时间】:2019-04-23 02:08:59
【问题描述】:

我的问题和这个很相似:

How to unit-test an action, when return type is ActionResult?

问题是我的问题混合在 generic ActionResult&lt;T&gt; 类型、asyncOk(...) 中。我似乎无法使链接问题的答案适应一般情况。或者可能我的情况略有不同。

这是一个复制品。创建“API”类型的新 ASP.NET Core Web 应用程序。向解决方案添加一个新的 xUnit .NET Core 测试项目,该项目引用 API 项目(以及任何所需的框架库)。分别像这样创建控制器和测试:

public class Thing { public string Name => "Foobar"; }
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
    [HttpGet]
    public async Task<ActionResult<Thing>> Get()
    {
        // The real "Thing" would be asynchronously retrieved from the DB
        return Ok(new Thing());
    }
}
[Fact]
public async Task Test1()
{
    var controller = new ValuesController();
    var actionResult = await controller.Get();
    Assert.NotNull(actionResult.Value);
    Assert.Equal("Foobar", actionResult.Value.Name);
}

这个测试没有变成绿色,而是在NotNull 断言上失败了(或者,如果我没有那个断言,它会抛出一个NullReferenceException)。

在调试和检查类层次结构后,我发现这似乎给出了预期的结果:

[Fact]
public async Task Test1()
{
    var controller = new ValuesController();
    var actionResult = await controller.Get();
    var okResult = actionResult.Result as OkObjectResult;
    var realResult = okResult?.Value as Thing;
    Assert.Equal("Foobar", realResult?.Name);
}

但这感觉就像我做错了什么。实际上,我有两个相关的问题:

  1. 是否有另一种惯用的方法来编写这个测试,它会折叠所有 as 演员表?
  2. 为什么第一个示例可以编译,却给出运行时异常?这是怎么回事?

【问题讨论】:

  • 在第二个示例中,您没有做错任何事情。这里有更多信息,底部是一个方便的扩展方法,可以帮助你的第一个测试工作更具可读性github.com/aspnet/Mvc/issues/8235
  • @AdamVincent 谢谢你,那个扩展方法其实解释的挺多的! ??????

标签: c# asp.net-core xunit


【解决方案1】:

使用 XUnit,您可以使用 T t = Assert.IsType&lt;T&gt;(other)。如果可能,这将进行强制转换,否则会导致测试失败。

例如我做这样的事情:

IActionResult actionResult = await Controller.GetItem(id);
OkObjectResult okObjectResult = Assert.IsType<OkObjectResult>(actionResult);
Model model = Assert.IsType<Model>(okObjectResult.Value);
Assert.Equal(id, model.Id);

至于你的第二个问题,事情可以在运行时抛出空引用异常并正确编译。这个问题将通过 C# 8 和不可为空的类型来解决。

【讨论】:

  • 谢谢,Assert.IsType 的两条线已经比我的 3 条 as 线好。我仍然有点困惑,为什么第一行不能直接得到ActionResult&lt;Model&gt;,但也许如果我以后重新审视事情,事情就会落实到位。
猜你喜欢
  • 2013-09-22
  • 2018-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-25
  • 2017-05-28
  • 2013-04-16
相关资源
最近更新 更多