当前位置:  开发笔记 > 编程语言 > 正文

单元测试HttpContext.Current.Cache或C#中的其他服务器端方法?

如何解决《单元测试HttpContext.Current.Cache或C#中的其他服务器端方法?》经验,为你挑选了5个好方法。

当创建一个使用的类的单元测试HttpContext.Current.Cache类,我使用NUnit时得到一个错误.功能是基本的 - 检查项目是否在缓存中,如果没有,则创建它并将其放入:

if (HttpContext.Current.Cache["Some_Key"] == null) {
    myObject = new Object();
    HttpContext.Current.Cache.Insert("Some_Key", myObject);
}
else {
    myObject = HttpContext.Current.Cache.Get("Some_Key");
}

当从单元测试中调用它NullReferenceException时,它在遇到第一Cache行时失败.在Java中,我会使用Cactus来测试服务器端代码.我可以使用类似的工具用于C#代码吗? 这个问题提到了模拟框架 - 这是我测试这些方法的唯一方法吗?是否有类似的工具来运行C#测试?

此外,我不检查是否Cache为null,因为我不想专门为单元测试编写代码,并假设它在服务器上运行时始终有效.这是有效的,还是应该在缓存周围添加空检查?



1> Orion Edward..:

这样做的方法是避免直接使用HttpContext或其他类似的类,并用模拟替换它们.毕竟,你不是试图测试HttpContext是否正常运行(这是微软的工作),你只是试图测试方法是否应该被调用.

步骤(如果您只想了解技术而不需要挖掘大量博客):

    创建一个界面,描述您希望在缓存中使用的方法(可能是GetItem,SetItem,ExpireItem等).称之为ICache或任何你喜欢的

    创建一个实现该接口的类,并将方法传递给真正的HttpContext

    创建一个实现相同接口的类,就像模拟缓存一样.如果您关心保存对象,它可以使用Dictionary或其他东西

    更改原始代码,使其根本不使用HttpContext,而只使用ICache.然后代码将需要获取ICache的实例 - 您可以在类构造函数中传递一个实例(这就是依赖注入的真正原因),或者将其粘贴到某个全局变量中.

    在您的生产应用程序中,将ICache设置为您真正的HttpContext-Backed-Cache,并在单元测试中将ICache设置为模拟缓存.

    利润!



2> Brian Surowi..:

我同意其他人使用界面是最好的选择,但有时改变现有系统是不可行的.这里有一些代码,我只是从我的一个项目中混合在一起,它可以为您提供所需的结果.这是漂亮的或最好的解决方案中最远的东西,但如果你真的无法改变你的代码那么它应该完成工作.

using System;
using System.IO;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Web;
using NUnit.Framework;
using NUnit.Framework.SyntaxHelpers;

[TestFixture]
public class HttpContextCreation
{
    [Test]
    public void TestCache()
    {
        var context = CreateHttpContext("index.aspx", "http://tempuri.org/index.aspx", null);
        var result = RunInstanceMethod(Thread.CurrentThread, "GetIllogicalCallContext", new object[] { });
        SetPrivateInstanceFieldValue(result, "m_HostContext", context);

        Assert.That(HttpContext.Current.Cache["val"], Is.Null);

        HttpContext.Current.Cache["val"] = "testValue";
        Assert.That(HttpContext.Current.Cache["val"], Is.EqualTo("testValue"));
    }

    private static HttpContext CreateHttpContext(string fileName, string url, string queryString)
    {
        var sb = new StringBuilder();
        var sw = new StringWriter(sb);
        var hres = new HttpResponse(sw);
        var hreq = new HttpRequest(fileName, url, queryString);
        var httpc = new HttpContext(hreq, hres);
        return httpc;
    }

    private static object RunInstanceMethod(object source, string method, object[] objParams)
    {
        var flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
        var type = source.GetType();
        var m = type.GetMethod(method, flags);
        if (m == null)
        {
            throw new ArgumentException(string.Format("There is no method '{0}' for type '{1}'.", method, type));
        }

        var objRet = m.Invoke(source, objParams);
        return objRet;
    }

    public static void SetPrivateInstanceFieldValue(object source, string memberName, object value)
    {
        var field = source.GetType().GetField(memberName, BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance);
        if (field == null)
        {
            throw new ArgumentException(string.Format("Could not find the private instance field '{0}'", memberName));
        }

        field.SetValue(source, value);
    }
}



3> Shawn Miller..:
HttpContext.Current = new HttpContext(new HttpRequest(null, "http://tempuri.org", null), new HttpResponse(null));



4> Steve Wright..:

如果您使用的是.NET 3.5,则可以在应用程序中使用System.Web.Abstractions.

Justin Etheredge 在如何模拟HttpContext(包含缓存类)方面有一篇很棒的文章.

从Justin的例子中,我使用HttpContextFactory.GetHttpContext将HttpContextBase传递给我的控制器.在模拟它们时,我只是构建一个模拟来调用缓存对象.


您可以使用HttpContextBase模拟几乎任何内容,但Cache属性不在其中.HttpContextBase.Cache的类型为System.Web.Caching.Cache,它是密封的,在单元测试中不可用而且不可模拟......

5> ClearCloud8..:

有一种更新的方法可以帮助在单元测试中专门处理Cache.

我建议使用微软新的MemoryCache.Default方法.您将需要使用.NET Framework 4.0或更高版本,并包含对System.Runtime.Caching的引用.

请参阅此处的文章 - > http://msdn.microsoft.com/en-us/library/dd997357(v=vs.100).aspx

MemoryCache.Default适用于Web和非Web应用程序.因此,您的想法是更新您的webapp以删除对HttpContext.Current.Cache的引用,并将其替换为对MemoryCache.Default的引用.稍后,当您运行决定单元测试这些相同的方法时,缓存对象仍然可用,并且不会为空.(因为它不依赖于HttpContext.)

这样您甚至不一定需要模拟缓存组件.

推荐阅读
N个小灰流_701
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有