如何在单元测试中模拟Cookie

本文关键字:模拟 Cookie 单元测试 | 更新日期: 2023-09-27 18:07:12

我有一个MVC控制器,我正在其中创建cookie并执行其余的操作。我需要对这个方法进行单元测试。我不知道如何嘲笑饼干。

这是我在控制器中的方法:

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

在这一行Response.Cookies.Add(usercookie);它给了我一个Null错误。当我追踪的时候,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添加到响应中,但不工作并得到相同的问题:

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

如何在单元测试中模拟Cookie

我认为你可以通过在你的控制器中做一些重构来处理这个问题,例如,你可以创建一个ICookieManager接口和一个CookieManager类(这个类包含添加cookie的逻辑,也实现了ICookieManager接口)然后你可以将这个ICookieManager作为一个依赖项添加到你的构造函数中或者作为一个属性然后你就可以在单元测试中模拟这个依赖项,像这样:

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