[英]ASP.net: Unit testing with dependency on web service proxy class
假設我有一個類似以下的類:
public class Test{
private RemoteDoc.Documentation docService = new RemoteDoc.Documentation();
public Test(){}
}
因此,由於依賴於代理類,因此很難進行單元測試。 您可以通過構造函數傳遞對象,如下所示:
public class Test{
private RemoteDoc.Documentation docService;
public Test(RemoteDoc.Documentation serv)
{
docService = serv;
}
}
現在,在單元測試中,我可以實例化Test類並將模擬對象傳遞給構造函數。 但是,此解決方案並不理想,因為現在其他類都必須了解RemoteDoc.Documentation代理類並對其有明確的引用。 什么是解決這個問題的好方法?
編輯:更清楚地說,RemoteDoc.Documentation是Web參考的代理類。 如果您使用的是salesforce.com的api,而您真正擁有的只是wsdl和disco文件,則可以將其想象為。
實際上,您建議的涉及通過構造函數傳遞依賴項的解決方案是理想的。 這是眾所周知的依賴注入(DI)模式,稱為構造函數注入 。
起初似乎是弱點,實際上是一種力量。 盡管確實確實每個Test類的使用者(在您的示例中)現在都必須提供代理的某種實現(我在此假設代理是接口或抽象基類),但他們可以提供該抽象的任何實現,並且不僅是您最初的想法。 恭喜: 您剛剛開設了可擴展性課程 !
這仍然留下了一個問題,即您將決定將哪些依賴項實際放到哪里的責任到底在哪里? 您應該在應用程序的根目錄(稱為“ 合成根目錄”)中執行此操作。 在此SO答案中對此進行了更詳細的說明。
您可以使用DI容器自動連線您的視線。 一些常見的DI容器是:
我喜歡RichardOD的方法。 對單元測試有用的一種改進是使用模擬對象而不是訪問實際的Web服務。 這意味着您的測試將與任何外部服務分離,並且運行速度更快。
如果代碼更改為以下形式,則可以執行以下操作:
public class Test
{
private RemoteDoc.IDocumentation docService;
// Constructor providing default for docService
public Test()
{
docService = new RemoteDoc.Documentation();
}
// Constructor for injection
public Test(RemoteDoc.IDocumentation serv)
{
docService = serv;
}
}
然后,使用如下模擬框架創建模擬文檔對象:
...並將其傳遞給Test(RemoteDoc.IDocumentation serv)構造函數。
由於RemoteDoc.Documentation是一個具體的類,因此您可以使用部分類使其從RemoteDoc.IDocumentation繼承:
namespace RemoteDoc
{
public interface IDocumentation
{
// public functions you want to mock go here
string GetDocumentation();
}
public partial class Documentation : IDocumentation {}
}
我贊成馬克的做法。 為了完整性,另一個選擇如下:
public class Test
{
private RemoteDoc.Documentation docService;
// Constructor providing default for docService
public Test()
{
docService = new RemoteDoc.Documentation();
}
// Constructor for injection
public Test(RemoteDoc.Documentation serv)
{
docService = serv;
}
}
這意味着您擁有默認的實現,並且可以選擇插入其他實現。 如果您不想使用容器,則很有用。
我過去曾經使用過兩種方法。 在開發非常規軟件時,通常使用DI容器方法是一種更好的方法。
請注意,使用WCF更加容易,因為服務合同已經是接口。 您的模擬類僅需要實現接口。
這種方法怎么樣? 您將不得不編寫更多代碼來支持代理類中的功能。 但這將為您提供單元測試的靈活性。
public interface IDocumentation
{
// Add whatever functionality you need from RemoteDoc.Documentation
}
public class RemoteDocumnetation : IDocumentation
{
private RemoteDoc.Documentation docService = new RemoteDoc.Documentation();
// Implements IDocumentation
}
public class Test{
private IDocumentation doc;
public Test(IDocumentation serv)
{
doc= serv;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.