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 );
...
这没有任何效果。
在编写问题时,您不需要设置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());
}
}