20

我正在尝试Setup返回对扩展方法的调用并收到:

SetUp : System.NotSupportedException : Expression references a method that does not belong to the mocked object: m => m.Cache.GetOrStore<String>("CacheKey", () => "Foo", 900)

GetOrStore引用作为扩展方法的 Cache 对象上的方法似乎有问题。

代码可以编译,但测试因此异常而失败。

我需要做什么来设置这样的扩展方法的结果?

4

3 回答 3

31

扩展方法不能像实例方法一样被模拟,因为它们没有在你的模拟类型上定义。它们在其他静态类中定义。由于您不能简单地模拟这些,您应该模拟扩展方法使用的所有方法/属性。

这是扩展方法如何将您的代码与其他类紧密耦合的示例。无论你做什么,你的类都依赖于那些静态方法。你不能模拟它并孤立地测试它。如果内部有任何逻辑,我建议重构您的代码以将这些方法移动到它们自己的类中。

于 2012-05-23T08:40:56.070 回答
5

Moq 无法模拟静态方法,因此您将无法模拟您的GetOrStore扩展。

取而代之的是模拟对象的GetandInsert方法Cache

于 2012-05-23T08:36:33.093 回答
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);

请注意,此代码未经测试,但应该解释基本思想。

于 2017-05-29T12:22:33.450 回答