[英]Best practices for using Mocks in TDD (MOQ)
我是新手使用Mocks。 但它的主要目的是什么? 我將首先使用Moq來測試我的應用程序(和NUnit)。
例如,我有代碼執行以下操作:
我的網頁代碼背后:
public partial class MyWebpage
{
protected string GetTitle(string myVar)
{
return dataLayer.GetTitle(myVar);
}
}
我的數據訪問層:
public class DataLayer
{
public string GetTitle(string myVar)
{
// Create the query we want
string query = "SELECT title FROM MyTable " +
"WHERE var = @myVar";
//ENTER PARAMETERS IN HERE
// Now return the result to the view
return this.dataProvider.ExecuteMySelectQuery(
dr =>
{
//DELEGATE DATA READER PASSED IN AND TITLE GETS RETURNED
},
query,
parameters);
}
}
我的數據提供者直接與數據庫進行對話和交互:
public class DataProvider
{
public T ExecuteMySelectQuery<T>(Func<IDataReader, T> getMyResult, string selectQuery, Dictionary parameters)
{
//RUNS AND RETURNS THE QUERY
}
}
測試所有這些的最佳方法是什么?
如果要單獨測試圖層,則需要為DataProvider和DataLayer類創建接口,以顯示您想要模擬的方法。 然后你可以使用一個模擬框架 - NSubstitute非常好,編寫更少的代碼來創建模擬 - 模擬對依賴類的調用,讓你測試該特定單元內的代碼
public interface IDataProvider
{
T ExecuteMySelectQuery<T>(Func<IDataReader, T> getMyResult, string selectQuery, Dictionary parameters);
}
public interface IDataLayer
{
string GetTitle(string myVar);
}
public class DataLayer
{
private IDataProvider dataProvider;
public DataLayer(IDataProvider dataProvider)
{
this.dataProvider = dataProvider;
}
}
然后,在測試代碼中,創建模擬而不是真實對象,並在實例化測試對象時將它們傳遞給構造函數。 要測試DataLayer:
[Test]
public void WhenRetievingTitleFromDataStore_ThenDataLayerReturnsTitle()
{
var title = "Title";
var dataProviderMock = new Mock<IDataProvider>(MockBehavior.Strict);
dataProviderMock.Setup(x => x.ExecuteMySelectQuery(<parameters>)).Returns(title);
var dataLayer = new DataLayer(dataProviderMock.Object);
Assert.That(dataLayer.GetTitle(It.IsAny<string>(), Is.EqualTo(title));
}
唯一可能出錯的是DB調用(查詢或返回的結果是錯誤的數據類型)。 這不能被嘲笑。 您需要進行集成測試而不是單元測試。
通常,您只能模擬能夠在代碼中測試邏輯。 您應該進行測試,以便數據映射器( this.dataProvider.ExecuteMySelectQuery
)按照定義工作。 但那是有問題的代碼的范圍。
更新
所以你有以下課程:
public class DataLayer
{
public string GetTitle(string myVar)
{
// Create the query we want
string query = "SELECT title FROM MyTable " +
"WHERE var = @myVar";
//ENTER PARAMETERS IN HERE
// Now return the result to the view
return this.dataProvider.ExecuteMySelectQuery(
dr =>
{
//DELEGATE DATA READER PASSED IN AND TITLE GETS RETURNED
},
query,
parameters);
}
}
public class DataProvider
{
public T ExecuteMySelectQuery<T>(Func<IDataReader, T> getMyResult, string selectQuery, Dictionary parameters)
{
//RUNS AND RETURNS THE QUERY
}
}
如果我們檢查ExecuteMySelectQuery
我們可以看到DataLayer
類依賴於數據庫返回的類型,因為DataProvider
只是簡化了查詢的執行。 可以說它是ADO.NET之上的插件。
這也意味着你永遠不能保證DataLayer
在不涉及數據庫的情況下返回所承諾的內容。 例如,假設數據庫中的table
有一個名為title
的列,但有人設法使用int
數據類型。
可能出錯的事情是
在模擬的幫助下,這些錯誤都不能被檢測到或測試。
另一方面,如果你在另一個類中使用DataLayer
clas,你當然可以模擬它。 因為DataLayer
類本身就是一個完整的抽象。 這意味着該類的調用者不必知道它下面的任何東西。 因此,嘲弄完全沒問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.