Как использовать moq для проверки конкретного метода в абстрактном классе? - PullRequest
15 голосов
/ 07 октября 2011

В прошлом, когда я хотел макетировать абстрактный класс, я просто создавал в коде фиктивный класс, который расширял абстрактный класс, а затем использовал этот класс в своем модульном тестировании ...

public abstract class MyConverter : IValueConverter
{
    public abstract Object Convert(...) { ... };

    public virtual Object ConvertBack(...) { ... }
}

private sealed class MockedConverter : MyConverter { ... }

[TestMethod]
public void TestMethod1()
{
    var mock = new MockedConverter();

    var expected = ...;
    var actual = mock.ConvertBack(...);

    Assert.AreEqual(expected, actual);
}

Я хочу привыкнуть использовать Мок вместо этого.Я не уверен, как бы я использовал Moq для проверки значения по умолчанию моего абстрактного класса.Любой совет здесь?

Ответы [ 3 ]

24 голосов
/ 07 октября 2011

Если вы установите для CallBase значение true, это вызовет реализацию базового класса.

var mock = new Mock<MyConverter> { CallBase = true };

См. Настройка Mock Behavior НастройкаMock Behavior раздел Быстрого старта.

Вызывает реализацию базового класса, если ожидание не переопределяет члена (иначе говоря, «Частичные насмешки» в насмешках носорога): по умолчанию - false.

5 голосов
/ 07 октября 2011

Вы можете установить Mock на абстрактный класс, как на интерфейсе. Чтобы протестировать абстрактную реализацию, вам нужно установить фиктивный объект для вызова базового метода для любых функций, которые не определены:

var mock = new Mock<MyConverter>();
mock.CallBase = true;
Assert.AreEqual(expected value,mock.Object.ConvertBack(...));
2 голосов
/ 07 октября 2011

Вы читали какое-нибудь руководство по началу работы для Moq?Это довольно просто:

var mock = new Mock<MyConverter>();
var expected = ...;
mock.Setup(m => m.ConvertBack(...)).Returns(expected);
var actual = m.Object.ConvertBack(...);
Assert.AreEqual(expected, actual);

Но, конечно, это плохой пример, потому что вы на самом деле не позволяете ему тестировать реальные классы.Насмешка полезна для обеспечения насмешки над реальным классом, для которого вы хотите выполнить модульное тестирование и который, как вы ожидаете, вызовет смоделированный вами метод.

Обновление

После прочтения вашего вопроса снова (с заголовком, обновленным Энтони Пеграмом), мне интересно, пытаетесь ли вы проверить реальную реализацию ConvertBack, высмеивая реализацию Convert.Если это так, у меня есть пара наблюдений:

  1. ConvertBack, вероятно, не следует объявлять virtual, по крайней мере, в этом примере,
  2. ВыВозможно, вы захотите провести рефакторинг вашего кода, чтобы Convert и ConvertBack были частью разных сервисов: я чувствую запах кода, возможно, вызванный отсутствием разделения проблем.

Если вы 'Убедитесь, что вам нужно сделать это, но все равно должно быть относительно просто:

var mock = new Mock<MyConverter>() {CallBase = true}; // hat tip: adrift
mock.Setup(m => m.Convert(...)).Returns(...);
var expected = ...;
var actual = m.Object.ConvertBack(...);
Assert.AreEqual(expected, actual);
...