问题
Here's my code:
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);
}
}
And my Unit Test code:
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);
But it still calls the original method and not the mocked one. Both classes exist in same assembly.
I have searched about it and almost all people got it right with CallBase = true
or false
.
Any ideas what is wrong with above code?
回答1:
As has been suggested by @Pierre-Luc in the comments, extracting the base class and injecting it as a dependency is probably the better approach (I always think mocking the class you're actually trying to test feels wrong).
That said, for you to be able to mock a call of a class, it needs to be made via the VTable. Essentially, the mocking framework creates a new implementation of the virtual method. When you call it normally, this version of the method is run and can then intercept calls. The problematic line is this one:
return base.MethodA(e1 => e1.Name.Equals(str), e2 => e2.TheBar);
Because you're explicitly calling MethodA
, via the base
keyword, it tells the compiler to call a particular version of the method. It's always going to call the base implementation. This means that the mock can't intercept the call.
Changing the method to:
public Foo DerviedMethod(string str) {
return MethodA(e1 => e1.Name.Equals(str), e2 => e2.TheBar);
}
Allows the MethodA
method to be mocked. Whether or not this is the right thing from a design perspective is up to you.
来源:https://stackoverflow.com/questions/31198854/original-method-still-getting-called-in-moq-even-after-callbase-true-false