2017-07-03 3 views
0

私はC#で何らかのデータベース操作(2-3のDB操作)を持つメソッドをテストするためにユニットテストを書いています。それ。私たちは多くのデータベース操作を内部に持っているメソッドを模倣することができます

private static APIResponse SubmitRequest(HttpWebRequest request, string info) 
    { 
     APIResponse responseObj = new APIResponse(); 

     WebResponse response = null; 
     // save the log into database. 
     Log.Request(request.Method + " to " + request.RequestUri.ToString() + ": " + info); 

     try 
     { 
      response = request.GetResponse(); 
     } 
     catch (WebException e) 
     { 
      var resp = (HttpWebResponse)e.Response; 

      if (resp.StatusCode == HttpStatusCode.NotModified) 
      { 
       responseObj.StatusCode = HttpStatusCode.NotModified; 
       responseObj.Headers = resp.Headers; 

       eTAG = responseObj.Headers["eTag"]; 

       // save the log into the database. 
       Log.Response("<empty>"); 

       return responseObj; 
      } 

      // save the log into the database. 
      Log.Warning(e.Message); 
      response = e.Response; 
     } 

     if (response == null) 
     { 
     Log.Response("<null>"); 
      return null; 
     } 

     StreamReader reader = new StreamReader(response.GetResponseStream()); 
     string textResponse = reader.ReadToEnd(); 

     HttpStatusCode status = ((HttpWebResponse)response).StatusCode; 
     reader.Close(); 
     response.Close(); 

     if (textResponse != null) 
     { 
      textResponse = textResponse.Trim(); 
     } 
     // save the log into the database. 
     Log.Response(textResponse.Length == 0 ? "<empty>" : textResponse); 

     if (textResponse.Length == 0) 
      return null; 

     responseObj.Headers = response.Headers; 
     responseObj.Message = textResponse; 
     responseObj.StatusCode = status; 

     eTAG = responseObj.Headers["eTag"]; 

     return responseObj; 
} 

スニペットでわかるように、コード間でさまざまな時間にログをデータベースに保存しています。どのようにしてこれらのログを模擬/停止して保存できますか?

public static void Request(string text) 
    { 
     -- code to save the code in db. 
    } 

public static void Response(string text) 
    { 
     -- code to save the code in db. 
    } 

どうすれば達成できますか?誰でも推測する?

+0

ユニットテストしたいメソッドのコードを追加できますか? – Scrobi

+1

一般に、データベース呼び出しを行うクラスを依存関係として抽出し、コンストラクター経由で注入したいとします。そうすれば、クラスのテストバージョン/モックをインスタンス化し、テストするクラスに渡すことができます – Stuart

+0

これは*非常に*広い質問です。データレイヤー自体を模擬してダミーデータを返すこともできますし、IQueryable(もしあれば)を模擬して実際のテーブルの代わりにDictionaryを使うこともできます。 EFを使用する場合、EFコンテキストをモックすることができます。実際のものではなくSQLiteのメモリ内DBを使用することができます。 EFコアには、テスト用のメモリ内DBもあります。 –

答えて

1

だから、Moqを使って、あなたはテストをしています。テストしたいクラスは、このように見えます。

public class ClassToTest 
{ 
    IDataAccessService _dataAccessService; 
    public ClassTotest(IDataAccessService dataAccessService) 
    { 
     _dataAccessService = dataAccessService; 
    } 
    public int SomeMethodWeWantToTest() 
    { 
     // Do Something. 
    } 
} 

ここでは、依存性注入を使用してDALを注入します。そのようにしてテスト時に私たちは模擬試験に合格することができます。

public class ConcreteDataAccessService : IDataAccessService 
{ 
    public List<int> GetSomeNumbersFromTheDatabase() 
    { 
     // Call db. 
     // Get some numbers. 
     // Return a list of them. 
    } 
} 

public IDataAccessService 
{ 
    List<int> GetSomeNumbersFromTheDatabase(); 
} 

ここでは、私たちのDALを表すインターフェイスを示します。我々は、インターフェイスIDataAccessServiceを実装する具体的な実装を持っています。この具体的な実装は、非テスト実行時に呼び出すことができます。

[TestClass] 
public class ClassToTestTests 
{ 
    [TestMethod] 
    public void SomeMethodWeWantToTest_ShouldAddUpAllNumbersFromDatabaseCorrectly() 
    { 
      Mock<IDataAccessService> dataAccessServiceMock = new Mock<IDataAccessService>(); 
      dataAccessService.Setup(x=>x.GetSomeNumbersFromTheDatabase()).Returns(new List<int>{1,2,3,4,5}); 
      ClassToTest classToTest = new ClassToTest(dataAccessService.Object()); 
      int expected = 15; 
      Assert.AreEqual(expected, classToTest.SomeMethodWeWantToTest()); 
    } 
} 

テストクラスはDataAccessServiceを模擬するために部品番号、モックフレームワークを使用していますし、我々はメソッドGetSomeNumbersFromTheDatabaseを呼び出すときに返すようにしたいものを設定します。

次に、テストするクラスをインスタンス化し、模擬したDataAccessServiceをクラスコンストラクタに渡します。

このようにして、ClassToTest.SomeMethodWeWantToTest()の機能を実際のデータベースにぶつかることなくテストできます。

このコードはコンパイルまたはチェックされていません。それはどのように行うか、非常に基本的なDIとテストの概要です。あなたはあなたの質問に任意のコードを提供していませんでした...

+0

Stuartありがとう、私は既存のコードをリファクタリングしており、そのためにいくつかのテストを書いています。しかし、欠点は、ソリューション内にデータアクセス層がないため、実現するのが少し難しいということです。この場合の助けに感謝します。 –

+0

私はLogクラスの周りにラッパーを作成し、あなたが提供した2つのメソッドだけで、その上にインターフェイスを配置します。次に、そのメソッドを示したクラスのコンストラクタに渡します。その後、インタフェース上のメソッドを呼び出します。テスト時にInterfaceをモックできます。 – Stuart

+0

ええ、確かに私の目標は、Log.ResponseまたはLog.Requestを擬似するだけでなく、これらのログ保存メソッドを含む "SubmitRequest"メソッド全体としてです。 –

関連する問題