简体   繁体   English

这是模拟HttpContextBase,HttpRequestBase和HttpResponseBase进行单元测试Cookie的正确方法吗?

[英]Is this the correct way to mock HttpContextBase, HttpRequestBase and HttpResponseBase for Unit Testing Cookies?

Given the following class to write and read cookies: 给定以下类来编写和读取cookie:

public static class CookieManager
{
    #region Methods

    /// <summary>
    ///     Writes a new cookie on the.
    /// </summary>
    /// <param name="response">The <see cref="HttpResponseBase"/> that is used to write the cookies.</param>
    /// <param name="name">The name of the cookie.</param>
    /// <param name="value">The value of the cookie.</param>
    public static void Write(HttpResponseBase response, string name, string value)
    {
        var applicationCookie = new HttpCookie(name) { Value = value, Expires = DateTime.Now.AddYears(1) };
        response.Cookies.Add(applicationCookie);
    }

    /// <summary>
    ///     Reads a cookie.
    /// </summary>
    /// <param name="request">The <see cref="HttpRequestBase"/> that is used to read cookies.</param>
    /// <param name="name">The name of the cookie to read.</param>
    /// <param name="defaultValue">The value to return when the cookie does not exists.</param>
    /// <returns>The value of the cookie if it's exists, otherwise the defautValue.</returns>
    public static string Read(HttpRequestBase request, string name, string defaultValue)
    {
        if (request.Cookies[name] != null)
        {
            return request.Cookies[name].Value;
        }

        return defaultValue;
    }

    /// <summary>
    ///     Check if a cookie does exists.
    /// </summary>
    /// <param name="request">The <see cref="HttpRequestBase"/> that is used to read cookies.</param>
    /// <param name="name">The name of the cookie.</param>
    /// <returns><see langword="true" /> when the cookie does exists, otherwise <see langword="false" />.</returns>
    public static bool Exists(HttpRequestBase request, string name)
    {
        if (request.Cookies[name] != null)
        {
            return true;
        }

        return false;
    }

    #endregion
}

Now, I do have a unit test and I want to test my CookieManager. 现在,我有一个单元测试,我想测试我的CookieManager。 Here's the unit test: 这是单元测试:

/// <summary>
///     Checks if the repository of the logs does contain an entry.
/// </summary>
[TestMethod]
public void then_the_cookie_should_be_present_in_the_cookiecollection()
{
    var context = new Mock<HttpContextBase>();
    var request = new Mock<HttpRequestBase>();
    var response = new Mock<HttpResponseBase>();

    response.SetupGet(x => x.Cookies).Returns(new HttpCookieCollection());
    request.SetupGet(x => x.Cookies).Returns(response.Object.Cookies);
    context.SetupGet(x => x.Request).Returns(request.Object);
    context.SetupGet(x => x.Response).Returns(response.Object);

    CookieManager.Write(response.Object, "CookieName", "CookieValue");
    var cookie = CookieManager.Read(request.Object, "CookieName", "Default");

    Assert.AreEqual("CookieValue", cookie, "The value retrieved from the cookie is incorrect.");
}

I know that this test is working, but I want to make sure that it's the correct way of testing or if there is any better solution. 我知道该测试正在运行,但是我想确保这是正确的测试方法,或者是否有更好的解决方案。

I know CodeReview, but I do think the question is best placed here. 我知道CodeReview,但是我认为这个问题最好放在这里。 If not, my aplogies. 如果没有,我表示歉意。

Testing against HttpContextBase is hard as it is closely coupled to the web framework. 由于HttpContextBase与Web框架紧密耦合,因此很难进行测试。 So the HttpContextBase class can be thought as Humble Object Pattern . 因此,可以将HttpContextBase类视为谦虚对象模式 This means that you don't necessarily need to test the logic in HttpContextBase. 这意味着您不一定需要测试HttpContextBase中的逻辑。

To make HttpContextBase humble, you need to extract abstraction from logic of HttpContextBase as the following. 为了使HttpContextBase谦虚,您需要按照以下方法从HttpContextBase的逻辑中提取抽象。

public interface ICookies
{
    string this[string name]{ get; set; }
}

And then, you can create the humble class, which isn't under test. 然后,您可以创建一个未经测试的谦虚类。

public class Cookies : ICookies
{
    public string this[string name]
    {
        get
        {
            var cookie = HttpContext.Current.Request.Cookies[name];
            if (cookie == null)
                throw new KeyNotFoundException();
            return cookie.Value;
        }
        set
        {
            var cookie = HttpContext.Current.Request.Cookies[name];
            if (cookie == null)
                throw new KeyNotFoundException();
            cookie.Value = value;
        }
    }
}

Your target class will be changed as below. 您的目标课程将如下更改。

public static class CookieManager
{
    public static void Write(ICookies cookies, string name, string value)
    {
        ...
    }

    ...
}

This would not be the best, but if I fall into your case, I will do like this. 这不是最好的,但是如果我落入您的案子,我会这样做。

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

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