Я очень ценю Moq Loose
mocking поведение, которое возвращает значения по умолчанию, когда ожидания не установлены. Это удобно и сохраняет код, а также действует как мера безопасности: зависимости не будут непреднамеренно вызваны во время unit test (пока они виртуальны).
Однако я смущен тем, как сохранить эти преимущества, когда тестируемый метод оказывается виртуальным.
В этом случае я действительно хочу назвать реальный код для этого метода, оставаясь при этом остальным классом, слегка издевающимся.
Все, что я нашел в своем поиске, это то, что я могу установить mock.CallBase = true
, чтобы гарантировать, что метод будет вызван. Однако это влияет на весь класс. Я не хочу этого делать, потому что это ставит меня в дилемму обо всех других свойствах и методах в классе, которые скрывают зависимости между вызовами: если CallBase является истинным, тогда я должен либо
- Настройка заглушек для всех свойств и методов, которые скрывают зависимости. Несмотря на то, что мой тест не считает, что он должен заботиться об этих зависимостях, или
- Надеюсь, что я не забуду установить какие-либо заглушки (и что в будущем в код не будут добавлены новые зависимости). Тесты блоков риска влияют на реальную зависимость.
То, что я думаю, я хочу, это что-то вроде: mock.Setup(m => m.VirtualMethod()).CallBase();
так что, когда я вызываю mock.Object.VirtualMethod()
, Moq вызывает реальную реализацию...
Q: С Moq, есть ли способ проверить виртуальный метод, когда я издевался над классом, чтобы заглушить только несколько зависимостей? То есть Не прибегая к CallBase = true и нужно заглушить все зависимости?
Пример кода для иллюстрации (использует MSTest, InternalsVisibleTo DynamicProxyGenAssembly2)
В следующем примере TestNonVirtualMethod
проходит, но TestVirtualMethod
fail - возвращает null.
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";
}