所以我有以下课程:

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 以来,我一直在这样的假设下进行。目的.A(),对 B() 的调用不会通过模拟,但这对我来说确实没有任何意义,因为来自任何其他对象的调用都会同样工作......

那么到底为什么模拟的设置没有被执行呢?

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

至于真正的代码,不幸的是它是非常专有的,所以我不能发布它。我明天看看是否可以调整代码以使其真正编译。

有帮助吗?

解决方案

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

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

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

其他提示

为了成功模拟方法,您的模拟对象必须满足以下条件:

  • 它必须是一个接口
  • 或者您想要模拟的方法必须是虚拟方法并且是公共的。

现在您还可以模拟虚拟内部方法,但为了允许您必须授予 Moq 访问内部的权限。您可以这样做:

[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]

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

所以为了嘲笑你 MyClass.A 打电话你必须这样做:

  1. 让你的方法A虚拟。
  2. 并将您的方法公开或允许访问

    [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
    

或者如前所述,创建一个代表 MyClass API 的接口。

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

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

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

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

var testObject= new Mock<MyClass> { CallBase = true };
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top