即使CallBase =真/假原来的方法仍然得到调用起订量 [英] Original method still getting called in Moq even after CallBase = true/false

查看:422
本文介绍了即使CallBase =真/假原来的方法仍然得到调用起订量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的代码:

  public class Bar {} 

public class Foo {public string Name {get;组; } public Bar TheBar {get;组; }}

public class依赖关系
{
public Foo DoSomething(Expression< Func< Foo,bool>> exp1){return new Foo }
}

public class Base
{
public Dependency Dependency {get;组; }
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);
}
}

strong>

  var mock = new Mock< Derived& {CallBase = true}; //与false相同的结果
mock
.Setup(m => m.MethodA(
It.IsAny< Expression< Func< Foo,bool>> b $ b It.IsAny< Expression< Func< Foo,object>>>()
))


// Act
var result = mock.Object.DerviedMethod(test);

// Assert
Assert.IsNotNull(result);

但它仍然调用原始方法,而不是模拟的方法。这两个类存在于同一程序集中。



我已经搜索过了,几乎所有人都用 CallBase = true



任何想法上面的代码有什么问题?


<正如@ 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 方法被嘲笑。从设计角度来看这是否正确取决于你。


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?

解决方案

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.

这篇关于即使CallBase =真/假原来的方法仍然得到调用起订量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆