Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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

Source is

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

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. enter image description here

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

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
840 views
Welcome To Ask or Share your Answers For Others

1 Answer

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> 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; }

Source

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

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

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...