簡體   English   中英

單元測試 Controller 方法返回 null

[英]Unit Testing a Controller method returns null

我正在嘗試通過測試 controller function GetProduct來學習 .NET 6 中的單元測試。 問題是我在變量var product = await _productController.GetProduct(productId); . 正如您在下圖中看到的, Result是好的,但Value ,其中ServiceResponse<Product>應該是 null。

在此處輸入圖像描述

這是 controller function:

public class ProductController : ControllerBase
{
    private readonly IProductService _productService;

    public ProductController(IProductService productService)
    {
        _productService = productService;
    }

    [HttpGet("{productId}")]
    public async Task<ActionResult<ServiceResponse<Product>>> GetProduct(int productId)
    {
        var result = await _productService.GetProductAsync(productId);
        return Ok(result);
    }
}

這是測試:

public class ProductControllerTest
{
    private readonly ProductController _productController;
    private readonly Mock<IProductService> _productService = new Mock<IProductService>();

    public ProductControllerTest()
    {
        _productController = new ProductController(_productService.Object);
    }    

    [Test]
    public async Task GetProducts_ReturnsProduct_IfProductExists()
    {
        //Arange
        var productId = 1;
        var prodData = new Product
        {
            Id = productId,
            Title = "null"            
        };
        var prductResponse = new ServiceResponse<Product>
        {
            Data = prodData,
            Success = true ,
            Message = ""
        };

        _productService.Setup(x => x.GetProductAsync(productId)).ReturnsAsync(prductResponse);

        //Act
        var product = await _productController.GetProduct(productId);

        //Assert
        Assert.That(product?.Value?.Data?.Id, Is.EqualTo(productId));
    }

}

由於您在 controller 中返回 Ok 調用,因此您可以向單元測試添加強制轉換。

   var result = (await _productController.GetProduct(productId)).Result as OkObjectResult;
   Assert.IsNotNull(result);
   var returnedServiceResponse = result.Value as ServiceResponse<Product>;
   Assert.That(returnedServiceResponse ?.Data?.Id, Is.EqualTo(productId));

此外,您不必使用 Actionresult。 您也可以只返回您的服務響應

   [HttpGet("{productId}")]
    public async Task<ServiceResponse<Product>> GetProduct(int productId)
    {
        var result = await _productService.GetProductAsync(productId);
        return result;
    }

這也將使測試更容易一些,因為不需要使用 OkObjectResult。

由於ActionResult<T> class 上的重載運算符,觀察到此行為。

由於方法 OK(value) 返回一個 OKObjectResult 的實例,並且 controller 方法的返回類型是ActionResult<ServiceResponse<Product>>返回的 OKObjectResult 實例被包裝在ActionResult<T>的實例中,並由Result暴露財產。 因此,將 Result 屬性(如@BennyM 所示)類型轉換為 OKObjectResult 是可行的。

請注意,如果 controller 方法直接返回ServiceResponse<Product>而不修改控制器方法的返回類型,則斷言會成功。

雖然這解釋了這種行為,但我個人覺得有更好的方法來測試控制器。 這篇MSDN 文章解釋了集成測試。 可以通過 mocking 對各個控制器的直接依賴項有效地對控制器的所有維度進行單元測試 - 身份驗證、驗證、(反)序列化等。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM