[英]How to substitute Object.ToString using NSubstitute?
當我嘗試使用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());
}
失敗:
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);
有沒有辦法讓上面的測試通過?
從我的天真測試中拋出異常是一個錯誤還是“按設計”?
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);
我們在這里調用“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());
}
但這很好用:
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());
}
對不起,我無法提供更好的消息,但嘲笑低級別對象在.Net中效果不佳。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.