【问题标题】:How Add test cookie to Request in C# unit test如何在 C# 单元测试中将测试 cookie 添加到请求
【发布时间】:2017-05-29 11:22:53
【问题描述】:

如何将测试 cookie 添加到请求中,以便从单元测试中测试我的代码。考虑这样的代码:

public ActionResult Dashboard()
{
    if (Request.Cookies["usercookie"] == null)
    {
        return RedirectToAction("Index");
    }
    return View();
}

我模拟所有内容,但我不知道如何向 cookie 添加一些内容,因此 Request.Cookies["usercookie"] 这一行不返回 null。现在它为空并返回此错误:

{"对象引用未设置为对象的实例。"}

这是我的单元测试方法之一:

[TestMethod]
[TestCategory("Unit")]
public void Login_ShouldValidateUserAndLoginSuccessfully()
{
    using (var kernel = new NSubstituteMockingKernel())
    {
        // Setup the dependency incjection
        kernel.Load(new EntityFrameworkTestingNSubstituteModule());

        // Create test request data 
        var request = new LogInRequest { UserName = "test", Password = "test" };

        var fakeResponseHandler = new FakeResponseHandler();
        fakeResponseHandler.AddFakeResponse(new Uri("http://localhost/test"), new HttpResponseMessage(HttpStatusCode.OK));
        ConfigurationManager.AppSettings["SearchApiBaseUrl"] = "http://test/internal";
        var server = new HttpServer(new HttpConfiguration(), fakeResponseHandler);
        var httpClient = new HttpClient(server);

        var fakeCookieManager = new FakeCookieManager();
        var authenticationService = Substitute.For<IAuthenticationService>();
        var newUser = Fake.GetNewUser(1);
        var newUserClaim = Fake.GetNewUserClaim(1, newUser.Id, "http://test/identity/claims/loans");
        authenticationService.GetUserByEmailPasswordAsync(request.UserName, request.Password).Returns(newUser);
        authenticationService.GetUserClaimByEmailAndPasswordAsync(request.UserName, request.Password).Returns(newUserClaim);
        var controller = new HomeController(httpClient, fakeCookieManager, null, authenticationService);
        Fake.SetFakeAuthenticatedControllerContext(controller);
        controller.HttpContext.Session["ReturnUrl"] = "/search"; 
        var result = controller.Login(request);
        Assert.IsNotNull(result);
    }
}

这是Fake for Httpcontext中的一个类:

    public static HttpContextBase InitialiseFakeHttpContext(string url = "")
    {
        var HttpContextSub = Substitute.For<HttpContextBase>();
        var RequestSub = Substitute.For<HttpRequestBase>();
        var ResponseSub = Substitute.For<HttpResponseBase>();
        var serverUtilitySub = Substitute.For<HttpServerUtilityBase>();
        var itemsSub = Substitute.For<IDictionary>();
        HttpContextSub.Request.Returns(RequestSub);
        HttpContextSub.Response.Returns(ResponseSub);
        HttpContextSub.Server.Returns(serverUtilitySub);
        var cookie = Substitute.For<HttpResponseBase>();
        HttpContextSub.Response.Returns(cookie);
        return HttpContextSub;
    }

【问题讨论】:

  • 在单元测试中显示你到目前为止所做的事情
  • @Nkosi 已添加到问题中。
  • 是的,您将需要使用伪造的 httpcontext 来控制上下文,该请求有一个请求,您可以在其中设置 http cookie 集合以适合您的单元测试。应该足够简单,可以伪造或模拟

标签: c# asp.net-mvc unit-testing cookies nsubstitute


【解决方案1】:

这是一个示例单元测试,其中在请求中设置了 cookie。

使用 NSubstitute 框架模拟 http 上下文,然后设置请求 cookie 属性。将模拟的 http 上下文应用于控制器上下文以模拟请求。

[TestClass]
public class MyControllerTests {
    [TestMethod]
    public void Request_Cookies_Should_Not_Be_Null() {
        //Arrange
        var cookies = new HttpCookieCollection();
        cookies.Add(new HttpCookie("usercookie"));

        var mockHttpContext = Substitute.For<HttpContextBase>();
        mockHttpContext.Request.Cookies.Returns(cookies);

        var sut = new MyController();
        sut.ControllerContext = new ControllerContext {
            Controller = sut,
            HttpContext = mockHttpContext
        };

        //Act
        var result = sut.Dashboard() as ViewResult;

        //Assert
        Assert.IsNotNull(result);
    }

    public class MyController : Controller {
        public ActionResult Dashboard() {
            if (Request.Cookies["usercookie"] == null) {
                return RedirectToAction("Index");
            }
            return View();
        }
    }
}

更新:

这是使用手动创建的模拟 HttpContext 进行测试的更新版本。

[TestClass]
public class MyControllerTests {
    [TestMethod]
    public void Request_Cookies_Should_Not_Be_Null() {
        //Arrange
        var cookies = new HttpCookieCollection();
        cookies.Add(new HttpCookie("usercookie"));

        var mockHttpContext = new MockHttpContext(cookies);

        var sut = new MyController();
        sut.ControllerContext = new ControllerContext {
            Controller = sut,
            HttpContext = mockHttpContext
        };

        //Act
        var result = sut.Dashboard() as ViewResult;

        //Assert
        Assert.IsNotNull(result);
    }

    public class MyController : Controller {
        public ActionResult Dashboard() {
            if (Request.Cookies["usercookie"] == null) {
                return RedirectToAction("Index");
            }
            return View();
        }
    }


    private class MockHttpContext : HttpContextBase {
        private readonly MockRequest request;
        public MockHttpContext(HttpCookieCollection cookies) {
            this.request = new MockRequest(cookies);
        }

        public override HttpRequestBase Request {
            get {
                return request;
            }
        }

        public class MockRequest : HttpRequestBase {
            private readonly HttpCookieCollection cookies;
            public MockRequest(HttpCookieCollection cookies) {
                this.cookies = cookies;
            }

            public override HttpCookieCollection Cookies {
                get {
                    return cookies;
                }
            }
        }

    }
}

【讨论】:

    【解决方案2】:

    使用 MOQ 框架也是一样

    用于模拟 HTTP 上下文的 MockContext 类

    public class MockContext
    {
        public Mock<RequestContext> RoutingRequestContext { get; private set; }
        public Mock<HttpContextBase> Http { get; private set; }
        public Mock<HttpServerUtilityBase> Server { get; private set; }
        public Mock<HttpResponseBase> Response { get; private set; }
        public Mock<HttpRequestBase> Request { get; private set; }
        public Mock<HttpSessionStateBase> Session { get; private set; }
        public Mock<ActionExecutingContext> ActionExecuting { get; private set; }
        public HttpCookieCollection Cookies { get; private set; }
    
        public MockContext()
        {
            this.RoutingRequestContext  = new Mock<RequestContext>(MockBehavior.Loose);
            this.ActionExecuting        = new Mock<ActionExecutingContext>(MockBehavior.Loose);
            this.Http                   = new Mock<HttpContextBase>(MockBehavior.Loose);
            this.Server                 = new Mock<HttpServerUtilityBase>(MockBehavior.Loose);
            this.Response               = new Mock<HttpResponseBase>(MockBehavior.Loose);
            this.Request                = new Mock<HttpRequestBase>(MockBehavior.Loose);
            this.Session                = new Mock<HttpSessionStateBase>(MockBehavior.Loose);
            this.Cookies                = new HttpCookieCollection();
    
            this.RoutingRequestContext.SetupGet (c => c.HttpContext).Returns(this.Http.Object);
            this.ActionExecuting.SetupGet       (c => c.HttpContext).Returns(this.Http.Object);
            this.Http.SetupGet                  (c => c.Request).Returns(this.Request.Object);
            this.Http.SetupGet                  (c => c.Response).Returns(this.Response.Object);
            this.Http.SetupGet                  (c => c.Server).Returns(this.Server.Object);
            this.Http.SetupGet                  (c => c.Session).Returns(this.Session.Object);
            this.Request.Setup                  (c => c.Cookies).Returns(Cookies);
        }
    
    }
    

    这是测试用例

    public void IndexTest()
        {
            // arrange
            MockContext mockContext = new MockContext();
    
            #region creating cookie
            HttpCookie cookie = new HttpCookie(Constant.COOKIE_ADMIN_USER_INFO,
                                             Config.DefaultCountryID.ToString());
    
            cookie.Values.Add(Constant.COOKIE_ADMIN_VALUE_COUNTRY_ID,
                              Config.DefaultCountryID.ToString());
            cookie.Values.Add(Constant.COOKIE_ADMIN_VALUE_LANGUAGE_ID,
                              Config.DefaultLanguageID.ToString());
    
            mockContext.Cookies.Add(cookie);
            #endregion
            #region Creating controller
            ControllerContext controllerContex = new ControllerContext()
            {
                HttpContext = mockContext.Http.Object
            };
            HomeController controller = new HomeController()
            {
                ControllerContext = controllerContex
            };
            #endregion
    
            // act
            var output = (ViewResult)controller.Index();
            var result = output.ViewData;
    
            // assert
            result.ShouldNotBeNull();
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-04-06
      • 2016-03-17
      • 1970-01-01
      • 2019-01-19
      • 1970-01-01
      • 1970-01-01
      • 2011-12-07
      • 1970-01-01
      相关资源
      最近更新 更多