简体   繁体   English

在动作内部分配响应属性时对控制器动作进行单元测试

[英]Unit testing Controller Action when Response property is assigned inside of an action

I saw the very same issue in this post but none of the solutions works now in ASP.Net Core 2.2.我在这篇文章中看到了同样的问题,但现在没有一个解决方案在 ASP.Net Core 2.2 中有效。 When I debug the unit test the Response property is still null and thus the test fails.当我调试单元测试时,响应属性仍然为空,因此测试失败。 I have been reading the asp.net core docs for an answer how to mock the ControllerContext so that the Response property has a value but I couldn't find anything working.我一直在阅读 asp.net 核心文档以获得如何模拟ControllerContext以便 Response 属性具有值的答案,但我找不到任何工作。

Here is the line inside the action that makes troubles:这是造成麻烦的操作中的行:

Response.Headers.Add("Access-Control-Expose-Headers", "Content-Range");

So what I have ended up with in the unit test set up is:所以我在单元测试设置中最终得到的是:

        var routeData = new RouteData();
        routeData.Values.Add("controller", "Home");

        var headerDictionary = new HeaderDictionary();
        var response = new Mock<HttpResponse>();
        response.SetupGet(r => r.Headers).Returns(headerDictionary);

        var httpContext = new Mock<HttpContext>();
        httpContext.SetupGet(a => a.Response).Returns(response.Object);

        var actionContext = new ActionContext(
            httpContext.Object,
            routeData, 
            new ControllerActionDescriptor());

        _controller.ControllerContext = new ControllerContext(actionContext);

A lot of the setup can be avoided by using the DefaultHttpContext which would have the needed properties already populated.通过使用DefaultHttpContext可以避免许多设置,它已经填充了所需的属性。 This includes the Response and its members这包括Response及其成员

//..

var routeData = new RouteData();
routeData.Values.Add("controller", "Home");

var httpContext = DefaultHttpContext(); //<--

var actionContext = new ActionContext(
    httpContext,
    routeData, 
    new ControllerActionDescriptor());

_controller.ControllerContext = new ControllerContext(actionContext);

//...

After exercising the subject under test, the response can the obtained from the context used by the controller and desired behavior asserted.在运行被测对象之后,可以从控制器使用的上下文中获得响应并断言所需的行为。

//...

//Assert
var response = httpContext.Response;
var key = "Access-Control-Expose-Headers";
Assert.True(response.Headers.TryGetValues(key, out var value));
Assert.Equals("Content-Range", value.FirstOrDefault()

Finally I have managed to mock the Controller 's HttpContext with the following code:最后,我设法使用以下代码模拟了ControllerHttpContext

    protected void SetUpControllerContext(ClaimsPrincipal principal)
    {
        var headerDictionary = new HeaderDictionary();
        var response = new Mock<HttpResponse>();
        response.SetupGet(r => r.Headers).Returns(headerDictionary);

        var httpContext = new Mock<HttpContext>();
        httpContext.SetupGet(a => a.Response).Returns(response.Object);
        httpContext.SetupGet(a => a.User).Returns(principal);


        this.SutController.ControllerContext = new ControllerContext()
        {
            HttpContext = httpContext.Object
        };
    }

Now altering the Response property inside Controller 's actions is allowed and doesn't trigger an error.现在允许在Controller的操作中更改Response属性,并且不会触发错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM