我的问题与这一问题非常相似:
How to unit-test an action, when return type is ActionResult?
问题是我的问题混合在泛型 ActionResult<T>
类型,async
和Ok(...)
中。我似乎无法使链接问题的答案适应一般情况。也许我的情况有些微妙。
这是一个复制品。创建新的“ 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);
}
但是,感觉就像我做错了什么。实际上,我还有两个相关的问题:
as
类型的转换都崩溃了?答案 0 :(得分:1)
通过XUnit,您可以使用T t = Assert.IsType<T>(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和非空类型解决。