asp.net-mvc - 如何模拟asp.net mvc中的缓存对象?

标签 asp.net-mvc unit-testing mocking

如何模拟 ControllerContext 对象上的缓存对象以进行单元测试?我尝试创建如下所示的包装类(因为缓存对象是密封类),但没有成功。

var mockControllerContext = new Mock<ControllerContext>(); 
var mockhttpContext = new Mock<HttpContextBase>();            

mockhttpContext.SetupGet(o => o.Cache).Returns(
         new CacheWrapper(mockControllerContext.Object.HttpContext.Cache));

mockControllerContext.SetupGet(
                          o => o.HttpContext).Returns(mockhttpContext.Object);
this.tennisMatchupController.ControllerContext = mockControllerContext.Object; 

最佳答案

编辑:我找到了一种更简单的方法来做到这一点,至少当您使用空缓存进行测试时。使用 HttpRunTime.Cache 作为您对 HttpContext 的 Cache 属性的期望的返回值。对于更高级的场景,使用包装器和模拟可能仍然是更好的处理方法 - 例如,如果您需要测试缓存中的异常。

var httpContext = MockRepository.GenerateMock<HttpContextBase>();
httpContext.Expect( h => h.Cache ).Return( HttpRunTime.Cache ).Repeat.Any()

原文:

包装类是可行的方法,但我认为您将其应用在错误的地方。我会给我的 Controller 一个 CacheWrapper 属性,然后创建一个构造函数,允许我传入可以设置此属性的 CacheWrapper 实例。默认情况下, Controller 使用 HttpContext.Current.Cache 创建 CacheWrapper。在您的测试代码中,构造一个模拟 CacheWrapper 以传递到 Controller 的构造函数中。这样,您根本不需要创建模拟 Cache 对象——这很困难,因为它是一个密封类。

或者,您可以实例化 Cache 类的实例并返回它,因为它有一个公共(public)构造函数。使用模拟的优点是您可以验证缓存是否按照预期使用,因此我可能会使用包装器。

public class CacheWrapper
{
  private Cache Cache { get; set; }

  public CacheWrapper()
  {
     this.Cache = HttpContext.Current.Cache;
  }

  public virtual Object Add( string key,
                             Object value,
                             CacheDependency dependencies,
                             DateTime absoluteExpiration,
                             TimeSpan slidingExpiration,
                             CacheItemPriority priority,
                             CacheItemRemovedCallback onRemoveCallback )
  {
     this.Cache.Add( key,
                     value,
                     dependencies,
                     absoluteExpiration,
                     slidingExpiration,
                     priority,
                     onRemoveCallback );
  }

  ...wrap other methods...
}


public class BaseController : Controller
{
    private CacheWrapper { get; set; }

    public BaseController() : this(null) { }

    public BaseController( CacheWrapper cache )
    {
        this.CacheWrapper = cache ?? new CacheWrapper();
    }
}

[TestMethod]
public void CacheTest()
{
   var wrapper = MockRepository.GenerateMock<CacheWrapper>();

   wrapper.Expect( o => o.Add( ... ) ).Return( ... );

   var controller = new BaseController( wrapper );

   var result = controller.MyAction() as ViewResult;

   Assert.AreEqual( ... );

   wrapper.VerifyAllExpectations();
}

关于asp.net-mvc - 如何模拟asp.net mvc中的缓存对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/783228/

相关文章:

asp.net-mvc - SessionSecurityTokenHandler 尝试使用 DPAPI 解密 RSA 加密的 cookie 中的 SessionSecurityToken;为什么?

c# - 如何让 YUI 编辑器传递其内容

c# - 单元测试实用方法

unit-testing - dotnet 核心的无约束隔离(模拟)框架

python - 如何使用 Mock 库修补 Python 类

jquery - 未捕获 RangeError : Maximum call stack size exceeded - Asp.net Mvc DropDown 与 Web Api 绑定(bind)

c# - 在模型内循环列表时使用 DisplayNameFor 和 DisplayFor

javascript - karma Jasmine 没有执行所有测试

javascript - Rewire - 同一模块中的模拟依赖

Python3模拟用另一个函数替换函数