Moq错误:无法强制转换';AnObject';到';System.Delegate';

本文关键字:AnObject Delegate System 转换 错误 Moq | 更新日期: 2023-09-27 18:27:45

我几天来一直试图解决这个问题,但都无济于事。我正在尝试测试AnObject.AnAction的功能(先发制人的抱歉,我必须混淆类/方法名。)我的目标是在调用MyTestObj.do_work(AnObject)时阻止它实际执行任何操作。它有我确实希望在单元测试环境中调用的代码。

这是我的单元测试代码:

Mock< MyTestObj > myTestObj_mock = new Mock< MyTestObj > ();
myTestObj_mock.Setup( e => e.do_work( It.IsAny< AnObject > () ) );
...
AnObject tester = new AnObject();
tester.anAction( myTestObj_mock.Object );

在方法AnObject.AnAction(MyTestObj mto)中:

...
mto.do_work( this );
...

正是在这一点上,当运行时,我得到了这个错误:

System.InvalidCastException : Unable to cast object of type  
'myNamespace.AnObject' to type 'System.Delegate'.     

MyTestObj.do_work是一个虚拟方法。

我完全不知道为什么会出现这个错误。我已经在NUnit运行代码的过程中逐步完成了它,我确信这就是它崩溃的地方。它不会进一步深入到代码中。

我真的被难住了。有人知道发生了什么事吗?

提前感谢!


**更新****

我试图在AnObject.AnAction中创建一个AnObject实例,并传递它而不是"this":

...
AnObject test = new AnObject();
mto.do_work( test );
...

这没有任何效果。

Moq错误:无法强制转换';AnObject';到';System.Delegate';

在编写问题时,您不需要设置myTestObj_mock.do_work().

Setup用来表示,当调用方法X时返回值Y。或者,当调用X时,返回异常Z。问问自己,这真的是我需要做的吗?

这里你没有从方法返回任何东西:

mto.do_work( this );

此外,这里:

myTestObj_mock.Setup( e => e.do_work( It.IsAny< AnObject > () ) );

您没有为您的设置定义任何Return。

在这种情况下,您应该能够在不定义设置的情况下提供mock myTestObj_mock。只需使用安装程序删除该行,然后再次运行测试。

猜测:

如果你定义设置是因为你想让你的测试确保AnObject.AnActivation真的调用do_work方法,你需要做的是定义一个Verify方法,而不是设置,同样:

mock.Verify(foo => foo.Execute("ping"));

或者在你的情况下类似

myTestObj_mock.Verify(m => m.do_work(It.IsAny< AnObject > ()), Times.AtLeastOnce());

另一种猜测:

如果您定义mock是因为您传递了一个"this"引用,并期望do_work修改"this"的一些参数以使测试通过,那么您不应该在这里进行mock。请记住,mock实际上并不是对象的实例,所以修改此引用的代码永远不会被调用。

我终于能够使用编译器来处理代码,下面是我的发现。这基本上就是贾尔斯在问题的第一部分所说的。

以下是安装程序的代码提示:

为对值返回方法的调用指定模拟类型的设置。

这是设置的实际代码

public ISetup<T> Setup(Expression<Action<T>> expression)

因此,Setup实际上是将代码设置为Action(基本上是委托)。当测试运行程序运行时,它达到了这一点,并且通常期望将委托提供给Returns方法

public IReturnsResult<TMock> Returns(TResult value)

因此,这永远不会完成,Mock并没有运行整个预期路径并协商出所有代码,而是返回了错误键入的值。

Sooo,这基本上就是Giles解释正确的地方。如果您正在测试do_work方法是否被调用,那么您希望使用Verify(它确实将您的假对象用作mock)。然而,如果没有,那么你甚至没有必要设置它,因为它什么都不做。如果是这样的话,那么也许这段代码不应该在那个特定的代码块中,但你最好评估一下。

最后,只有当您真正将对象用作存根时,才应该使用Setup方法,只需使用它将逻辑注入代码即可。

希望这是有道理的,能帮助你解决问题。

此外,Callback在这里可能有用,这取决于您正在做什么。但是,我不确定。他们在Moq快速启动中有很多例子

更新我尝试使用4.0.10827版本重新访问…并且没有问题

    [Test]
    public void teststuff()
    {
        Mock<MyTestObj> myTestObj_mock = new Mock<MyTestObj>();
        myTestObj_mock.Setup(e => e.do_work(It.IsAny<AnObject>()));
        AnObject tester = new AnObject();
        tester.anAction(myTestObj_mock.Object);
    }

public class MyTestObj
{
    public virtual void do_work(AnObject o)
    {
    }
}
public class AnObject
{
    public void anAction(MyTestObj obj)
    {
        obj.do_work(new AnObject());
    }
}