簡體   English   中英

如何使用NSubstitute替換Object.ToString?

[英]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類的方法。

  1. 它在Castle的IProxyGenerationHook默認實現中被抑制。 你可以在這里找到代碼。 我認為有理由這樣做。 當然,可以實現自己的IProxyGenerationHook,它允許Object類的方法攔截,但......

  2. 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM