4

私はモックを使うのは初めてです。しかし、それは主な目的は何ですか?まず、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);
    }
}

私のデータプロバイダーは、dbと直接通信して対話します。

 public class DataProvider
{
     public T ExecuteMySelectQuery<T>(Func<IDataReader, T> getMyResult, string selectQuery, Dictionary parameters)
    {
          //RUNS AND RETURNS THE QUERY
     }
}

これらすべてをテストするための最良の方法は何ですか?

4

2 に答える 2

3

レイヤーを個別にテストする場合は、モックするメソッドを公開する 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));
}
于 2012-12-07T08:41:09.277 に答える
2

これで問題が発生する可能性があるのは、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していることがわかります。ADO.NET 上のアドオンと言えます。DataLayerDataProvider

DataLayerこれは、データベースを使用せずに約束されたものを返すことを保証できないことも意味します。たとえばtable、データベースに という列titleがあるが、誰かがそのintデータ型を代わりに使用したとします。

うまくいかない可能性があるのは、

  • クエリが正しくありません
  • データベースのスキーマが正しくありません (列名、データ型が間違っているなど)
  • マッピング

これらのエラーは、モックを使用しても検出もテストもできません。

一方、DataLayerクラスを別のクラスで使用する場合は、もちろんそれをモックできます。DataLayerクラス自体が完全な抽象化であるためです。つまり、クラスの呼び出し元は、その下にあるものを認識する必要はありません。したがって、モックはまったく問題ありません。

于 2012-12-07T08:33:03.997 に答える