如何测试MVC控制器的状态码

5

我正在使用本地的 .net Visual Studio 测试工具来测试我的控制器。 尝试确保在此处(代码的开头)如果传递给控制器的内容未通过授权,则设置未经授权的状态代码。以下是我的控制器代码。

public class HubspotController : Controller
{
    [HttpPost]
    public ActionResult FreeDemo(string json)
    {
        JObject jobject = JObject.Parse(json);

        var password = jobject["person"]["password"]?.ToString();
        var username = jobject["person"]["username"]?.ToString();

        if (!AuthorizeUser(password, username))
        {
            StatusUnauthorized();
        }

        var resultStatus = new ResultStatus { Message = "success"};
        return Json(resultStatus, JsonRequestBehavior.AllowGet);
    }

    public ActionResult StatusUnauthorized()
    {
        return new HttpStatusCodeResult((int)HttpStatusCode.Unauthorized, "Unauthorized");
    }

    private bool AuthorizeUser(string password, string username)
    {
        return false;
    }
}

以下是我的测试。请耐心等待,因为我没有太多的测试经验,所以只是在尝试弄清楚这个问题。

[TestClass]
public class HubspotControllerFixture
{
    private Mock<HttpRequestBase> request;
    private Mock<HttpContextBase> httpContext;
    private Mock<HttpResponseBase> response;

    [TestInitialize]
    public void TestInitialize()
    {
        request = new Mock<HttpRequestBase>();
        request.SetupGet(r => r.ContentType).Returns("application/json");
        response = new Mock<HttpResponseBase>();
        httpContext = new Mock<HttpContextBase>();
        httpContext.SetupGet(c => c.Request).Returns(request.Object);
        httpContext.SetupGet(x => x.Response).Returns(response.Object);
    }

    [TestMethod]
    public void Status_Code_Gets_Set_To_Unauthorized()
    {
        var json = "{\"person\": {\"password\":\"abc123\", \"username\":\"user\", \"name\":\"test person\"}}";
        var controller = new HubspotController()
        {
            ControllerContext = new ControllerContext()
            {
                HttpContext = httpContext.Object
            }
        };
        controller.FreeDemo(json);
        Assert.AreEqual(HttpStatusCode.Unauthorized, httpContext.Object.Response.StatusCode);
    }
}

当我运行时,出现了错误。我做错了什么?

Assert.AreEqual 失败。期望值为:<未授权 (System.Net.HttpStatusCode)>。实际值为:<0 (System.Int32)>


我怀疑你无法在测试中使用http上下文,因为在测试代码中你并不处于请求/响应的情境中。 - Lasse V. Karlsen
2个回答

4
你的测试中断言的对象不正确。这个测试用例对HttpContext没有影响或依赖性。你需要断言你的被测方法的结果。
你首先需要更新你的目标控制器操作。
//...other code omitted for brevity
if (!AuthorizeUser(password, username))
{
    return StatusUnauthorized();
} 
//...other code omitted for brevity

现在您的测试看起来应该像这样,因为您实际上不需要模拟HttpContext进行此测试

[TestMethod]
public void Status_Code_Gets_Set_To_Unauthorized() {
    //Arrange
    var json = "{\"person\": {\"password\":\"abc123\", \"username\":\"user\", \"name\":\"test person\"}}";
    var controller = new HubspotController();
    var expected = (int)HttpStatusCode.Unauthorized;
    //Act
    var actionResult = controller.FreeDemo(json) as HttpStatusCodeResult;
    //Assert
    Assert.IsNotNull(actionResult);
    Assert.AreEqual(expected, actionResult.StatusCode);
}

我曾经对此感到困惑,但是由于返回的结果是0而不是401,我认为问题更深层次。但是我仍然更新了assert。现在我得到了预期:<401>。实际:<0>。 - geoff swartz
它也更深入。它是“0”的事实也表明你正在比较错误的东西。 - Nkosi
1
请注意,如果您返回的是Json/View,那么此方法将无法工作,因为它们无法强制转换为HttpResponseStatus。 - AaronLS
这是为了测试特定场景而设计的。显然,它不适用于您所指示的情况,并且必须针对其特定测试用例进行重构。 - Nkosi

0

我认为你漏掉了一个return语句。请见下面的更新代码。

public class HubspotController : Controller
{
    [HttpPost]
    public ActionResult FreeDemo(string json)
    {
        JObject jobject = JObject.Parse(json);

        var password = jobject["person"]["password"]?.ToString();
        var username = jobject["person"]["username"]?.ToString();

        if (!AuthorizeUser(password, username))
        {
            return StatusUnauthorized();
        }

        var resultStatus = new ResultStatus { Message = "success"};
        return Json(resultStatus, JsonRequestBehavior.AllowGet);
    }

    public ActionResult StatusUnauthorized()
    {
        return new HttpStatusCodeResult((int)HttpStatusCode.Unauthorized, "Unauthorized");
    }

    private bool AuthorizeUser(string password, string username)
    {
        return false;
    }
}

啊,我明白了。但是即使我加上那个返回语句,我仍然得到相同的错误/失败。 - geoff swartz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接