c# - 如何使用 ActionResult<T> 进行单元测试?

标签 c# unit-testing asp.net-core .net-core xunit

我有一个像这样的 xUnit 测试:

[Fact]
public async void GetLocationsCountAsync_WhenCalled_ReturnsLocationsCount()
{
    _locationsService.Setup(s => s.GetLocationsCountAsync("123")).ReturnsAsync(10);
    var controller = new LocationsController(_locationsService.Object, null)
    {
        ControllerContext = { HttpContext = SetupHttpContext().Object }
    };
    var actionResult = await controller.GetLocationsCountAsync();
    actionResult.Value.Should().Be(10);
    VerifyAll();
}

来源是

/// <summary>
/// Get the current number of locations for a user.
/// </summary>
/// <returns>A <see cref="int"></see>.</returns>
/// <response code="200">The current number of locations.</response>
[HttpGet]
[Route("count")]
public async Task<ActionResult<int>> GetLocationsCountAsync()
{
    return Ok(await _locations.GetLocationsCountAsync(User.APropertyOfTheUser()));
}

结果的值为 null,导致我的测试失败,但如果您查看 ActionResult.Result.Value(内部属性),它包含预期的解析值。

请参阅以下调试器的屏幕截图。 enter image description here

如何获取要在单元测试中填充的 actionResult.Value?

最佳答案

在运行时,由于隐式转换,您的原始测试代码仍然可以工作。

但是根据提供的调试器图像,测试似乎断言了结果的错误属性。

因此,虽然更改被测方法允许测试通过,但无论以哪种方式实时运行,它都会起作用

ActioResult<TValue>有两个属性,根据使用它的操作返回的内容进行设置。

/// <summary>
/// Gets the <see cref="ActionResult"/>.
/// </summary>
public ActionResult Result { get; }

/// <summary>
/// Gets the value.
/// </summary>
public TValue Value { get; }

Source

因此,当 Controller 操作使用 Ok() 返回时它会设置 ActionResult<int>.Result通过隐式转换操作结果的属性。

public static implicit operator ActionResult<TValue>(ActionResult result)
{
    return new ActionResult<TValue>(result);
}

但测试断言 Value属性(请参阅 OP 中的图像),在本例中未设置。

无需修改被测代码以满足测试,它就可以访问 Result属性并对该值进行断言

[Fact]
public async Task GetLocationsCountAsync_WhenCalled_ReturnsLocationsCount() {
    //Arrange
    _locationsService
        .Setup(_ => _.GetLocationsCountAsync(It.IsAny<string>()))
        .ReturnsAsync(10);
    var controller = new LocationsController(_locationsService.Object, null) {
        ControllerContext = { HttpContext = SetupHttpContext().Object }
    };

    //Act
    var actionResult = await controller.GetLocationsCountAsync();

    //Assert
    var result = actionResult.Result as OkObjectResult;
    result.Should().NotBeNull();
    result.Value.Should().Be(10);

    VerifyAll();
}

关于c# - 如何使用 ActionResult<T> 进行单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54237343/

相关文章:

c# - 使用 XmlNode 读取嵌套的 XML

php - HTML 输出的单元测试?

linux - 如何在 Mac 上从 asp.net vnext 运行 HelloWeb?

c# - 什么 block 没有被覆盖?

postgresql - 导入数据,重复键值违反唯一约束

c# - 在 WPF 自托管 asp.net 核心应用程序中加载 View

c# - 如何让协程有序运行?

c# - GetType() 和 GetTypes() 等反射 API 的性能如何?

c# - 需要左外连接类型时在 LINQ 中连接表的问题

java - 如何对抽象类进行单元测试 : extend with stubs?