2016-09-14 297 views
0

我有一个MVC控制器,我正在其中创建cookie并执行其余的操作。我需要单元测试这个方法。我不确定如何模拟cookie。单元测试如何模拟Cookie

这是我在控制器方法:在此行Response.Cookies.Add(usercookie)

public ActionResult Login(LogInRequest logInRequest) 
{ 
    if (ModelState.IsValid) 
    { 
     HttpCookie usercookie = new HttpCookie("usercookie"); 
     usercookie["UserName"] = logInRequest.UserName; 
     usercookie["Password"] = logInRequest.Password; 
     usercookie.Expires = DateTime.Now.AddMinutes(10); 
     **Response.Cookies.Add(usercookie);** 
     return RedirectToAction("search", "LoanDriver"); 
     ....... 
     return View(logInRequest); 
    } 

;它给了我一个错误,为空。当我追踪cookie时有价值。

这是我的测试方法:

public void Web_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://dev.loans.carfinance.com/internal"; 
     var server = new HttpServer(new HttpConfiguration(), fakeResponseHandler); 
     var httpClient = new HttpClient(server); 
     var controller = new LoanDriverController(httpClient); 
     Fake.SetFakeContext(controller); 
     var result = controller.Login(request); 
     Assert.IsNotNull(result); 
    } 
} 

我已尝试添加cookie来响应很好,但不是工作ANS得到同样的问题:

public static void SetFakeContext(this Controller controller) 
{ 
    var httpContext = InitialiseFakeHttpContext(); 
    ControllerContext context = 
     new ControllerContext(new RequestContext(httpContext, new RouteData()), controller); 
    controller.ControllerContext = context; 
} 

private 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; 
} 

回答

1

我认为你可以处理这个问题通过在你的控制器中进行一些重构,你可以创建一个ICookieManager接口和一个CookieManager类(这个类包含添加一个cookie的逻辑,也实现了ICookieManager接口),那么你可以添加这个ICookieManager作为你的依赖构造函数或as一个属性,然后你就可以嘲笑这种依赖在你的单元测试,这样的事情:

public interface ICookieManager 
    { 
     void CreateUserCookie(string userName, string password, HttpResponseBase response, int expiration = 10); 
    } 

    public class CookieManager: ICookieManager 
    { 
     public void CreateUserCookie(string userName, string password, HttpResponseBase response, int expiration = 10) 
     { 
      HttpCookie usercookie = new HttpCookie("usercookie"); 
      usercookie["UserName"] = userName; 
      usercookie["Password"] = password; 
      usercookie.Expires = DateTime.Now.AddMinutes(expiration); 
      response.Cookies.Add(usercookie); 
     } 
    } 

在你的控制器:

public class YourController : Controller 
    { 
     public ICookieManager CookieManager { get; set; } 

     public YourController() 
     { 
      CookieManager = new CookieManager(); 
     } 

     public YourController(ICookieManager cookieManager) 
     { 
      CookieManager = cookieManager; 
     } 

     public ActionResult Login(LogInRequest logInRequest) 
     { 
      if (ModelState.IsValid) 
      { 
       CookieManager.CreateUserCookie(logInRequest.UserName, logInRequest.Password, Response); 
       return RedirectToAction("search", "LoanDriver"); 
      } 
     } 


    } 

在你的单元测试:

public void Web_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://dev.loans.carfinance.com/internal"; 
      var server = new HttpServer(new HttpConfiguration(), fakeResponseHandler); 
      var httpClient = new HttpClient(server); 
      var controller = new LoanDriverController(httpClient); 
      controller.CookieManager=mockOfYourCookieManager; //here you pass the instance of the mock or also you can passe it in the constructor of the controller. 
      Fake.SetFakeContext(controller); 
      var result = controller.Login(request); 
      Assert.IsNotNull(result); 
     } 
+0

这是一个很好的答案。谢谢。 – Alma