2016-09-14 123 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