用 Moq 征服擴充法模擬:實用指南
有效的單元測試通常依賴模擬依賴項。 然而,模擬擴展方法(向現有介面添加功能)提出了獨特的挑戰。 讓我們來探討一下這個問題及其解決方案。
想像一個 ISomeInterface
及其在 SomeInterfaceExtensions
中定義的擴展方法。 Caller
類別使用 AnotherMethod
擴充:
<code class="language-csharp">public interface ISomeInterface { } public static class SomeInterfaceExtensions { public static void AnotherMethod(this ISomeInterface someInterface) { } } public class Caller { private readonly ISomeInterface someInterface; public Caller(ISomeInterface someInterface) { this.someInterface = someInterface; } public void Main() { someInterface.AnotherMethod(); } }</code>
測試Caller.Main()
需要模擬ISomeInterface
並驗證AnotherMethod
的呼叫。 然而,直接使用 Moq 模擬擴展方法會導致「非成員方法上的無效設定」錯誤。
問題的根源
Moq 的限制源自於擴展方法的本質。它們不是介面定義的一部分; Moq 依賴介面成員進行模擬。
包裝方法:一個強大的解決方案
一個實用的解決方案涉及建立一個封裝擴展方法邏輯的包裝類別:
<code class="language-csharp">public class SomeInterfaceExtensionWrapper { private readonly ISomeInterface wrappedInterface; public SomeInterfaceExtensionWrapper(ISomeInterface wrappedInterface) { this.wrappedInterface = wrappedInterface; } public void AnotherMethod() { wrappedInterface.AnotherMethod(); // Calls the extension method } }</code>
現在,測試可以模擬包裝器:
<code class="language-csharp">var wrapperMock = new Mock<SomeInterfaceExtensionWrapper>(); wrapperMock.Setup(x => x.AnotherMethod()).Verifiable(); var caller = new Caller(wrapperMock.Object); caller.Main(); wrapperMock.Verify();</code>
替代策略
雖然包裝器方法很有效,但它增加了複雜性。 考慮以下替代方案:
最佳方法取決於您的專案背景和優先順序。
以上是如何使用最小起訂量在單元測試中有效模擬擴充方法?的詳細內容。更多資訊請關注PHP中文網其他相關文章!