Moq在C#中设置混乱

时间:2009-11-25 22:57:24

标签: c# moq

所以我有以下课程:

public class MyClass {
  internal void A() {
    foreach(Thing thing in ThingArray)
      B(thing);
  }

  virtual internal void B(Thing thing)
  {
    //  do some stuff
  }
}

然后我有以下测试:

...
var testObject = new Mock<MyClass>(parameters);
testObject.Setup(t => t.B(It.IsAny<Thing>()));

test.Object.A();

test.Verify(t => t.B(It.IsAny<Thing>()), Times.Exactly(2));

验证失败了。我已经检查过了,代码调用了真正的 B()方法而不是模拟的B()方法。

我有很多代码在Moq完美运行的地方运行,我编码的时间足够长,以至于我必须在这里做错事,但对于我的生活,我看不到它。我一直在假设,因为我正在调用test。 Object .A(),对B()的调用不是通过Mock,但实际上并没有通过对我来说很有意义,因为来自任何其他对象的调用都会起作用......

那么为什么地球上没有被执行的模拟设置?

编辑:是的,我有测试项目可见的内部结构。我打算把它放到原帖中,因为我知道有人会提到它。

至于真正的代码,遗憾的是非常专有,所以我无法发布它。我明白是否可以明天调整代码以使其实际编译。

4 个答案:

答案 0 :(得分:7)

你的模拟对象必须符合这个标准才能成功模拟一个方法:

  • 必须是一个界面
  • 或者您要模拟的方法必须是虚拟方法并公开。

现在你也可以模拟虚拟内部方法,但是为了允许你必须让Moq访问你的内部。你可以这样做:

[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]

这使得内部可以访问Moq的代码生成器。

因此,为了模拟您的MyClass.A来电,您必须这样做:

  1. 让方法A虚拟。
  2. 并将您的方法设为公开或允许使用

    进行访问
    [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
    
  3. 或者如上所述,创建一个代表MyClass API的接口。

答案 1 :(得分:2)

我不确定Gamlor的答案是否有效。似乎如果要对要验证Class1.MethodA调用Class1.MethodB的方法执行设置,MethodB(您将进行设置的那个)必须是公共的(无论InternalsVisibleTo如何)。我在类似情况下编写了一个简单的测试,发现一旦我公开了我的MethodB,Moq就开始工作了。我敢打赌,如果你公开你的方法B,那就行了。

我认为这是一个Castle或Moq bug,但我不确定。希望有人会参与进来。

我知道让MethodB公开不是一个好选择。但这就是我对情况的了解......

答案 2 :(得分:0)

Moq不会包装现有代码,而是创建一个空模拟。

这意味着调用testObject.Object.A()不会执行原始代码,因此从不调用B.

如果你假装模拟一个接口,那么这是有道理的,因为接口没有代码,所以模拟器也不会。

答案 3 :(得分:0)

尝试像这样创建模拟(我没有尝试过,所以我不知道它是否有效):

var testObject= new Mock<MyClass> { CallBase = true };