У меня есть существующий интерфейс ...
public interface ISomeInterface
{
void SomeMethod();
}
и я расширил этот интерфейс, используя миксин ...
public static class SomeInterfaceExtensions
{
public static void AnotherMethod(this ISomeInterface someInterface)
{
// Implementation here
}
}
У меня есть класс, называющий это, который я хочу проверить ...
public class Caller
{
private readonly ISomeInterface someInterface;
public Caller(ISomeInterface someInterface)
{
this.someInterface = someInterface;
}
public void Main()
{
someInterface.AnotherMethod();
}
}
и тест, в котором я хотел бы смоделировать интерфейс и проверить вызов метода расширения ...
[Test]
public void Main_BasicCall_CallsAnotherMethod()
{
// Arrange
var someInterfaceMock = new Mock<ISomeInterface>();
someInterfaceMock.Setup(x => x.AnotherMethod()).Verifiable();
var caller = new Caller(someInterfaceMock.Object);
// Act
caller.Main();
// Assert
someInterfaceMock.Verify();
}
Запуск этого теста, однако, генерирует исключение ...
System.ArgumentException: Invalid setup on a non-member method:
x => x.AnotherMethod()
У меня вопрос, есть ли хороший способ сделать смешанный звонок?
c#
unit-testing
mocking
extension-methods
moq
Рассел Гиддингс
источник
источник
Ответы:
Вы не можете "напрямую" макетировать статический метод (следовательно, метод расширения) с помощью фреймворка. Вы можете попробовать Moles ( http://research.microsoft.com/en-us/projects/pex/downloads.aspx ), бесплатный инструмент от Microsoft, который реализует другой подход. Вот описание инструмента:
Вы можете использовать Кроты с любой средой тестирования (это не зависит от этого).
источник
Я использовал Обертку, чтобы обойти эту проблему. Создайте объект-обертку и передайте имитируемый метод.
См. Статические методы Mocking Static для модульного тестирования Пола Ирвина, там есть хорошие примеры.
источник
Я обнаружил, что мне нужно обнаружить внутреннюю часть метода расширения, для которого я пытался смоделировать ввод, и смоделировать то, что происходило внутри расширения.
Я рассматривал использование расширения как добавление кода непосредственно к вашему методу. Это означало, что мне нужно было высмеивать то, что происходит внутри расширения, а не само расширение.
источник
Вы можете смоделировать тестовый интерфейс, который наследуется от реального и имеет элемент с такой же сигнатурой, что и у метода расширения.
Затем вы можете смоделировать тестовый интерфейс, добавить реальный в макет и вызвать метод теста в настройке.
Ваша реализация макета может затем вызвать любой метод, который вы хотите, или просто проверить, что метод вызывается:
Спасибо решению Håvard S в этом посте за то, как реализовать макет, который поддерживает два интерфейса. Как только я нашел его, адаптировать его к тестовому интерфейсу и статическому методу было очень просто.
источник
SomeNotAnExtensionMethod
иSomeNotAnExtensionMethod
? Теперь у меня есть идея, как создать сигнатуру метода расширения внутри интерфейса ...iReal
параметрSomeExtensionMethod
в случаеITest
? Если вы передадите его в качестве первого параметра, то как вы настраиваете?Setup( x=> x.SomeExtensionMethod(x, ...)
это вызовет исключение во время выполнения.object _mockCache = whatever
... `Setup (x => x.SomeExtensionMethod (...) .. Callback (() => вы можете доступ к _mockCache здесь);)Вы можете легко смоделировать метод расширения с помощью JustMock . API - это то же самое, что и обычный метод насмешки. Рассмотрим следующее
Для организации и проверки этого метода используйте следующее:
Вот также ссылка на документацию: Методы расширения Mocking
источник
Мне нравится использовать обертку (шаблон адаптера), когда я обертываю сам объект. Я не уверен, что использовал бы это для переноса метода расширения, который не является частью объекта.
Я использую внутреннее свойство Lazy Injectable либо типа Action, Func, Predicate, либо делегата, и разрешаю вводить (заменять) метод во время модульного теста.
Затем вы вызываете Func вместо фактического метода.
Для более полного примера, проверьте http://www.rhyous.com/2016/08/11/unit-testing-calls-to-complex-extension-methods/
источник
Так что, если вы используете Moq и хотите смоделировать результат метода Extension, тогда вы можете использовать
SetupReturnsDefault<ReturnTypeOfExtensionMethod>(new ConcreteInstanceToReturn())
экземпляр класса mock, у которого есть метод extension, который вы пытаетесь смоделировать.Это не идеально, но для целей модульного тестирования это работает хорошо.
источник