如何测试返回 Ok(object) 的 ASP.NET Core 2.2 Web API GET IActionResult?

Posted

技术标签:

【中文标题】如何测试返回 Ok(object) 的 ASP.NET Core 2.2 Web API GET IActionResult?【英文标题】:How to test my ASP.NET Core 2.2 Web API GET IActionResult that returns Ok(object)? 【发布时间】:2020-08-26 09:09:15 【问题描述】:

在我的 Web API 中,我有一个简单的控制器操作:

[HttpGet]
[Route("[action]")]
public IActionResult GetApiStatus(string token)

    if (_token != token)
    
        return StatusCode(401);
    

    StatusModel status = _vesselUpdating.GetUpdatingStatus();

    return Ok(status);

并且操作返回StatusModel 类型的对象。我无法管理如何测试它的返回状态。

我的测试方法如下:

[Theory]
[InlineData("wrong_token", StatusCodes.Status401Unauthorized)]
[InlineData("test_token", StatusCodes.Status200OK)]
[InlineData("", StatusCodes.Status401Unauthorized)]
[InlineData(null, StatusCodes.Status401Unauthorized)]
public void Get_GetAnyAction_WithVariusTokens_ReturnsCorrectStatusCode(string token, int code)

    _vesselUpdatingMock.Setup(v => v.GetUpdatingStatus()).Returns(_sampleStatusModel);
    IActionResult result;

    result = _updatesController.GetApiStatus(token);
    StatusCodeResult resultGetApiStatus = result as StatusCodeResult;

    Assert.Equal(code, resultGetApiStatus.StatusCode);

在调试时

result = _updatesController.GetApiStatus(token);

IActionResultStatusCode 属性是 200,但只有 DeclaredType 的属性是 null

当断言时,最后我有我的resultGetApiStatus null

我没有找到类似的例子。如何正确投影result

重要编辑:

我发现只有this approach,这不能解决我的问题,关于各种情况[Theory],并不是我所有的其他操作都返回ObjectResult,其中一些只返回StatusCode。有和没有ObjectResult 的操作是否有任何通用方法?还是应该使用不同的测试?

【问题讨论】:

【参考方案1】:

这种挫败感不仅是你拥有的。

OkObjectResult 不继承自 StatusCodeResult,所以

StatusCodeResult resultGetApiStatus = result as StatusCodeResult;

正确地返回 null。

见:https://github.com/aspnet/Mvc/issues/7134

您应该能够强制使用IStatusCodeActionResult

https://github.com/dotnet/aspnetcore/blob/a410ed460140a55dd699e83d978b798de48802fb/src/Mvc/Mvc.Core/src/StatusCodeResult.cs#L32 但是,我不确定它附带哪个版本(2.1?)

[Theory]
[InlineData("wrong_token", StatusCodes.Status401Unauthorized)]
[InlineData("test_token", StatusCodes.Status200OK)]
[InlineData("", StatusCodes.Status401Unauthorized)]
[InlineData(null, StatusCodes.Status401Unauthorized)]
public void Get_GetAnyAction_WithVariusTokens_ReturnsCorrectStatusCode(string token, int code)

    _vesselUpdatingMock.Setup(v => v.GetUpdatingStatus()).Returns(_sampleStatusModel);

    var result = _updatesController.GetApiStatus(token);
    var resultGetApiStatus = result as IStatusCodeActionResult;

    Assert.Equal(code, resultGetApiStatus.StatusCode);

【讨论】:

根据文档,它是在 2.2 中添加的,因此根据标题中指示的版本 OP 仍然有效。 IStatusCodeActionResult 是我要找的 :)【参考方案2】:

测试逻辑存在缺陷,这也导致基于应用于被测对象的输入提供的结果好坏参半。

根据允许在受试者中测试一条逻辑路径的预期行为测试特定结果。

例如

[Theory]
[InlineData("wrong_token")]
[InlineData("")]
[InlineData(null)]
public void Get_GetAnyAction_WithInvalidTokens_ReturnsUnauthorizedStatusCode(string token) 
    //Arrange
    int expected = StatusCodes.Status401Unauthorized;

    //Act
    StatusCodeResult result = _updatesController.GetApiStatus(token) as StatusCodeResult;

    //Assert
    int actual = result.StatusCode;
    Assert.Equal(expected, actual);


[Fact]
public void Get_GetAnyAction_WithValidToken_ReturnsCorrectStatusCode() 
    //Arrange
    _vesselUpdatingMock.Setup(v => v.GetUpdatingStatus()).Returns(_sampleStatusModel);
    string token = "test_token";

    //Act
    OkObjectResult result = _updatesController.GetApiStatus(token) as OkObjectResult;

    //Assert
    int expected = StatusCodes.Status200OK;
    int actual = result.StatusCode;
    Assert.Equal(expected, actual);

这样你就避免了向测试添加条件逻辑,这意味着测试做了太多

【讨论】:

以上是关于如何测试返回 Ok(object) 的 ASP.NET Core 2.2 Web API GET IActionResult?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用postman带Token测试接口?

如何使用postman带Token测试接口?

如何在 shell 中获取测试命令返回码?

如何在Objective-C中测试字符串是否为空?

如何取出JAVA多层 object 内的某个值,如下结构:

shell脚本如何获取状态码返回值,如ok或error