Original method still getting called in Moq even after CallBase = true/false

匿名 (未验证) 提交于 2019-12-03 00:59:01

问题:

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.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!