我正在尝试Setup
返回对扩展方法的调用并且正在接收:
SetUp : System.NotSupportedException : Expression references a method that does not belong to the mocked object: m => m.Cache.GetOrStore<String>("CacheKey", () => "Foo", 900)
在Cache对象上引用GetOrStore
方法似乎存在问题,这是一种扩展方法。
代码编译但测试失败并出现此异常。
如何设置这样的扩展方法的结果需要做什么?
扩展方法不能像实例方法一样进行模拟,因为它们未在模拟类型上定义。它们在其他静态类中定义。由于您不能简单地模拟那些,您应该模拟扩展方法使用的所有方法/属性。
这是扩展方法如何将代码紧密耦合到其他类的示例。无论你做什么,你的班级都依赖于那些静态方法。你无法模仿并单独测试它。我建议重构你的代码,如果里面有任何逻辑,将这些方法移动到他们自己的类中。
Moq无法模拟静态方法,因此您将无法模拟您的GetOrStore
扩展。
而只是模拟Get
对象的Insert
和Cache
方法。
它有可能,虽然不是很漂亮......我假设你的扩展方法中有一些内部缓存对象,或某个地方某个缓存的引用。您可以使用反射替换内部对象来存储缓存。你在测试中得到这样的东西:
IFixture fixture = new Fixture().Customize(new AutoMoqCustomization());
Mock<ICache> internalCache = new Mock<ICache>();
internalCache.Setup(i => i.Get<String>("CacheKey")).Returns("Foo");
var cacheExtension = typeof(CacheExtensions);
var inst = cacheExtension.GetField("_internalCache", BindingFlags.NonPublic | BindingFlags.Static);
inst.SetValue(cacheExtension, internalCache.Object);
请注意,此代码未经过测试,但应解释基本概念。