簡體   English   中英

在TDD(MOQ)中使用Mocks的最佳實踐

[英]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.

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