简体   繁体   English

即使在CallBase = true / false之后,原始方法仍会在Moq中被调用

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

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 . 我已经搜索过它,几乎所有人都使用CallBase = truefalse正确了。

Any ideas what is wrong with above code? 任何想法上面的代码有什么问题吗?

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). 正如@ Pierre-Luc在评论中所建议的那样,提取基类并将其作为依赖项注入可能是更好的方法(我一直认为嘲笑您实际上试图测试的类感觉不对)。

That said, for you to be able to mock a call of a class, it needs to be made via the VTable. 也就是说,为了能够模拟类的调用,需要通过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. 因为您是通过base关键字显式调用MethodA ,所以它告诉编译器调用该方法的特定版本。 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. 允许MethodA方法。 Whether or not this is the right thing from a design perspective is up to you. 从设计的角度来看这是否正确取决于您。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM