Результат установки для вызова метода расширения
Я пытаюсь 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, который является методом расширения.
Код компилируется, но с этим исключением не выполняется.
Что мне нужно сделать, чтобы настроить результат такого метода расширения?
Ответы
Ответ 1
Методы расширения не могут быть издевательски похожи на методы экземпляра, поскольку они не определены в вашем издеваемом типе. Они определены в других статических классах. Поскольку вы не можете просто имитировать их, вместо этого вы должны издеваться над всеми методами/свойствами, используемыми методом расширения.
Это пример того, как методы расширения тесно связывают ваш код с другими классами. Независимо от того, что вы делаете, ваш класс зависит от этих статических методов. Вы не можете издеваться над этим и тестировать его изолированно. Я предлагаю рефакторинг вашего кода, чтобы переместить эти методы в свои классы, если внутри есть какая-либо логика.
Ответ 2
Moq не может издеваться над статическими методами, поэтому вы не сможете издеваться над расширением GetOrStore
.
Вместо этого просто издевайтесь над методами Get
и Insert
объекта Cache
.
Ответ 3
Возможно, хотя и не очень...
Я предполагаю, что внутри вашего метода расширения есть какой-то внутренний объект кеширования или где-то ссылка на некоторый кеш. Вы можете использовать отражение для замены внутреннего объекта для хранения кеша. В вашем тесте вы получите что-то подобное:
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);
Обратите внимание, что этот код не проверен, но он должен объяснить основную идею.