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

时间:2014-05-27 20:45:24

标签: c# unit-testing

给定以下类来编写和读取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
}

现在,我有一个单元测试,我想测试我的CookieManager。 这是单元测试:

/// <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.");
}

我知道这个测试正在运行,但我想确保它是正确的测试方式,或者是否有更好的解决方案。

我知道CodeReview,但我认为问题最好放在这里。如果没有,我的抱歉。

1 个答案:

答案 0 :(得分:2)

对HttpContextBase进行测试很困难,因为它与Web框架紧密耦合。因此HttpContextBase类可以被认为是Humble Object Pattern。这意味着您不一定需要在HttpContextBase中测试逻辑。

要使HttpContextBase谦逊,您需要从HttpContextBase的逻辑中提取抽象,如下所示。

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

然后,你可以创建一个不受测试的卑微课程。

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

您的目标类将更改如下。

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

    ...
}

这不是最好的,但如果我属于你的情况,我会这样做。