如何使用ActionResult< T>进行单元测试? [英] How to Unit Test with ActionResult<T>?

查看:153
本文介绍了如何使用ActionResult< T>进行单元测试?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个xUnit测试,例如:

I have a xUnit test like:

[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()));
}

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

The value of the result is null, causing my test to fail, but if you look at ActionResult.Result.Value (an internal property) it contains the expected resolved value.

请参阅以下是调试器的屏幕截图。

See the following screen capture of the debugger.

如何获取actionResult.Value填充到单元测试中?

How do I get the actionResult.Value to populate in a unit test?

推荐答案

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

At run time your original code under test would still work because of the implicit conversion.

但是根据所提供的调试器映像,看起来测试似乎在对结果的错误属性进行断言。

But based on the provided debugger image it looks like the test was asserting on the wrong property of the result.

因此,在更改被测方法时,测试可以通过,当以任何一种方式实时运行时都会起作用

So while changing the method under test allowed the test to pass, it would have worked when run live either way

ActioResult< TValue> 有两个属性,具体取决于

ActioResult<TValue> has two properties that are set depending on what is returned from the action that uses it.

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

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

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

So when the controller action returned using Ok() it would set the ActionResult<int>.Result property of the action result via implicit conversion.

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

但是测试断言了 Value 属性(请参阅OP中的图像),在这种情况下没有设置。

But the test was asserting the Value property (refer to image in OP), which in this case was not being set.

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

Without having to modify the code under test to satisfy the test it could have accessed the Result property and make assertions on that value

[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();
}

这篇关于如何使用ActionResult&lt; T&gt;进行单元测试?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆