我正在尝试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
方法似乎存在问题,这是一种扩展方法。
代码编译但测试因此异常而失败。
如何设置这样的扩展方法的结果需要做什么?
答案 0 :(得分:25)
扩展方法不能像实例方法一样进行模拟,因为它们没有在模拟类型上定义。它们在其他静态类中定义。由于你不能简单地模拟那些,你应该模拟扩展方法使用的所有方法/属性。
这是扩展方法如何将代码紧密耦合到其他类的示例。无论你做什么,你的班级都依赖于那些静态方法。你无法模仿并单独测试它。如果内部有任何逻辑,我建议重构你的代码,将这些方法移动到自己的类中。
答案 1 :(得分:5)
Moq无法模拟静态方法,因此您将无法模拟GetOrStore
扩展名。
而只是模仿Get
对象的Insert
和Cache
方法。
答案 2 :(得分:1)
有可能,虽然不漂亮...... 我假设您的扩展方法中有一些内部缓存对象,或者某处某个缓存的引用。您可以使用反射替换内部对象来存储缓存。你在测试中得到这样的东西:
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);
请注意,此代码未经过测试,但应解释基本概念。