当我尝试使用NSubstitute 1.7.1.0定义的行为Object.ToString(这是一个虚拟方法),NSubstitute被抛出异常.
重现:
[Test]
public static void ToString_CanBeSubstituted()
{
var o = Substitute.For<object>();
o.ToString().Returns("Hello world");
Assert.AreEqual("Hello world", o.ToString());
}
Run Code Online (Sandbox Code Playgroud)
失败:
NSubstitute.Exceptions.CouldNotSetReturnDueToNoLastCallException : Could not find a call to return from.
Make sure you called Returns() after calling your substitute (for example: mySub.SomeMethod().Returns(value)),
and that you are not configuring other substitutes within Returns() (for example, avoid this: mySub.SomeMethod().Returns(ConfigOtherSub())).
If you substituted for a class rather than an interface, check that the call to your substitute was on a virtual/abstract member.
Return values cannot be configured for non-virtual/non-abstract members.
Correct use:
mySub.SomeMethod().Returns(returnValue);
Potentially problematic use:
mySub.SomeMethod().Returns(ConfigOtherSub());
Instead try:
var returnValue = ConfigOtherSub();
mySub.SomeMethod().Returns(returnValue);
Run Code Online (Sandbox Code Playgroud)
有没有办法让上面的测试通过?
从我的天真测试中抛出异常是一个错误还是"按设计"?
NSubstitute基于Castle.Core库并使用动态代理来拦截和管理调用.在两个框架中都禁止拦截Object类的方法.
它在Castle的IProxyGenerationHook默认实现中被抑制.你可以在这里找到代码.我认为有理由这样做.当然,可以实现自己的IProxyGenerationHook,它允许Object类的方法拦截,但......
NSubstitute也抑制了对象方法的拦截,并且NSubstitute的语法就是原因."NSubstitute记录对替换的调用,当我们调用返回时,它会抓取最后一次调用并尝试配置它以返回特定值." 假设我们有以下代码:
var service = Substitute.For<IService>();
var substitute = Substitute.For<object>();
service.AMethod(substitute).Returns(1);
Run Code Online (Sandbox Code Playgroud)
我们在这里调用"AMethod()",NSub拦截执行并生成其内部事物,假设将"替换"值添加到调用substitute.GetHashCode()的字典中.如果我们拦截"GetHashCode()"方法,那么它将是最后记录的调用.NSub会将指定的返回值绑定到错误的位置.几乎不可能避免这样的事情.
您将无法替换任何方法,System.Object因为.Net非常特别地对待它.
例如,由于同样的原因,这也失败了:
[Test]
public void x()
{
var o = Substitute.For<anything>();
o.GetHashCode().Returns(3);
Assert.AreEqual(4, o.GetHashCode());
}
Run Code Online (Sandbox Code Playgroud)
但这很好用:
public class Anything {
public virtual string Else() {
return "wrong";
}
}
[Test]
public void x() {
var o = Substitute.For<Anything>();
o.Else().Returns("right");
Assert.AreEqual("right", o.Else());
}
Run Code Online (Sandbox Code Playgroud)
对不起,我无法提供更好的消息,但嘲笑低级别对象在.Net中效果不佳.
| 归档时间: |
|
| 查看次数: |
2923 次 |
| 最近记录: |