Мне очень нравится Moq's Loose
насмешливое поведение, которое возвращает значения по умолчанию, когда ожидания не установлены. Это удобно и экономит мой код, а также действует как мера безопасности: зависимости не будут вызываться непреднамеренно во время модульного теста (пока они виртуальные).
Однако я не совсем понимаю, как сохранить эти преимущества, когда тестируемый метод оказывается виртуальным.
В этом случае я делаю хочу вызвать реальный код для этого одного метода, в то же время оставляя остальную часть класса свободно посмешищем.
Все, что я нашел в своем поиске, - это то, что я могу установить mock.CallBase = true
, чтобы метод вызывался. Однако это влияет на весь класс. Я не хочу этого делать, потому что это ставит меня перед дилеммой по поводу всех других свойств и методов в классе, которые скрывают зависимости вызовов: если CallBase равен true, тогда мне нужно либо
- Настройка заглушки для всех свойств и методов, которые скрывают зависимости - хотя мой тест не считает, что нужно заботиться об этих зависимостях, или
- Надеюсь, что я не забуду установить любые заглушки (и что в будущем в код не будут добавлены новые зависимости) - модульные тесты риска достигают реальной зависимости.
Я думаю, что хочу что-то вроде:
mock.Setup(m => m.VirtualMethod()).CallBase();
так что когда я вызываю mock.Object.VirtualMethod()
, Moq вызывает реальную реализацию ...
В: С Moq, есть ли способ протестировать виртуальный метод, когда я высмеял класс, чтобы заглушить несколько зависимостей? То есть Не прибегая к CallBase = true и без необходимости заглушить все зависимости?
Пример кода для иллюстрации
(использует MSTest, InternalsVisibleTo DynamicProxyGenAssembly2)
В следующем примере TestNonVirtualMethod
проходит, но TestVirtualMethod
терпит неудачу - возвращает ноль.
public class Foo
{
public string NonVirtualMethod() { return GetDependencyA(); }
public virtual string VirtualMethod() { return GetDependencyA();}
internal virtual string GetDependencyA() { return "! Hit REAL Dependency A !"; }
// [... Possibly many other dependencies ...]
internal virtual string GetDependencyN() { return "! Hit REAL Dependency N !"; }
}
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestNonVirtualMethod()
{
var mockFoo = new Mock<Foo>();
mockFoo.Setup(m => m.GetDependencyA()).Returns(expectedResultString);
string result = mockFoo.Object.NonVirtualMethod();
Assert.AreEqual(expectedResultString, result);
}
[TestMethod]
public void TestVirtualMethod() // Fails
{
var mockFoo = new Mock<Foo>();
mockFoo.Setup(m => m.GetDependencyA()).Returns(expectedResultString);
// (I don't want to setup GetDependencyB ... GetDependencyN here)
string result = mockFoo.Object.VirtualMethod();
Assert.AreEqual(expectedResultString, result);
}
string expectedResultString = "Hit mock dependency A - OK";
}