Исходный метод по-прежнему вызывается в Moq даже после CallBase = true/false
Вот мой код:
public class Bar { }
public class Foo { public string Name { get; set; } public Bar TheBar { get; set; } }
public class Dependency
{
public Foo DoSomething(Expression<Func<Foo, bool>> exp1) { return new Foo(); }
}
public class Base
{
public Dependency Dependency { get; set; }
public virtual Foo MethodA(Expression<Func<Foo, bool>> exp1,
params Expression<Func<Foo, object>>[] exp2)
{
return Dependency.DoSomething(exp1);
}
}
public class Derived : Base
{
public Foo DerviedMethod(string str)
{
return base.MethodA(e1 => e1.Name.Equals(str), e2 => e2.TheBar);
}
}
И мой код модульного теста:
var mock = new Mock<Derived> { CallBase = true }; // Same result with false
mock
.Setup(m => m.MethodA(
It.IsAny<Expression<Func<Foo, bool>>>(),
It.IsAny<Expression<Func<Foo, object>>>()
))
.Returns(new Foo());
// Act
var result = mock.Object.DerviedMethod("test");
// Assert
Assert.IsNotNull(result);
Но он по-прежнему вызывает оригинальный метод, а не поддельный. Оба класса существуют в одной сборке.
Я искал об этом, и почти все люди поняли это правильно с CallBase = true
или же false
,
Есть идеи, что не так с приведенным выше кодом?
1 ответ
Как было предложено @Pierre-Luc в комментариях, извлечение базового класса и внедрение его в качестве зависимости, вероятно, является лучшим подходом (я всегда думаю, что издеваться над классом, который вы на самом деле пытаетесь проверить, кажется неправильным).
Тем не менее, для того, чтобы вы могли смоделировать вызов класса, это должно быть сделано через VTable. По сути, фреймворк создает новую реализацию виртуального метода. Когда вы вызываете его как обычно, эта версия метода запускается и может затем перехватывать вызовы. Проблемная черта такая:
return base.MethodA(e1 => e1.Name.Equals(str), e2 => e2.TheBar);
Потому что вы явно звоните MethodA
через base
ключевое слово, оно говорит компилятору вызвать конкретную версию метода. Это всегда будет вызывать базовую реализацию. Это означает, что макет не может перехватить вызов.
Изменение метода на:
public Foo DerviedMethod(string str) {
return MethodA(e1 => e1.Name.Equals(str), e2 => e2.TheBar);
}
Позволяет MethodA
метод для насмешек. Правильно ли это с точки зрения дизайна, решать только вам.