次のような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
(内部プロパティ)予期される解決済みの値が含まれます。
ユニットテストに入力するactionResult.Valueを取得するにはどうすればよいですか?
実行時には、暗黙的な変換のため、テスト中の元のコードは引き続き機能します。
しかし、提供されたデバッガーイメージに基づいて、テストが結果の間違ったプロパティでアサートしていたように見えます。
したがって、テスト中のメソッドを変更すると、テストに合格することができますが、いずれかの方法でライブで実行すると機能します。
_ActioResult<TValue>
_には、それを使用するアクションから何が返されるかに応じて設定される2つのプロパティがあります。
_/// <summary>
/// Gets the <see cref="ActionResult"/>.
/// </summary>
public ActionResult Result { get; }
/// <summary>
/// Gets the value.
/// </summary>
public TValue Value { get; }
_
そのため、コントローラアクションが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();
}
_
問題はそれをOk
でラップすることです。オブジェクト自体を返す場合、Value
は正しく入力されます。
ドキュメント内のMicrosoftの例 を見ると、NotFound
のようなデフォルト以外の応答に対してのみコントローラーメソッドを使用しています。
[HttpGet("{id}")]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult<Product> GetById(int id)
{
if (!_repository.TryGetProduct(id, out var product))
{
return NotFound();
}
return product;
}