2012-04-24 13 views
4

はRavenDBを使用して、次のブログ記事(http://www.codecapers.com/post/Using-RavenDB-with-ASPNET-MVC.aspx)で を述べた:IRepositoryはどのようにユニットテストができますか?私はリポジトリを使用して、以下の方法を書かれている

public User GetUserById(string id) 
{ 
    var user = (from usr in _repository.All<User>() where usr.Id == id select usr).FirstOrDefault(); 

    if (user == null) 
    { 
      throw new NullReferenceException("No user with the id (" + id + ") could be found."); 
    } 

    return user; 
} 

このメソッドをnunit(とおそらくmoq)で単体テストしますか?

"user"は通常のクラスです。

答えて

0

最初の質問は、この文脈では何をテストしていますか?実際に提供されるメソッドには2つの結果しかないので、基本的にはuserがnullかどうかをテストしています。それは付加価値テストですか?

については、の場合、_repositoryとは何らかのメカニズムで注入されていますか?その場合は、Mock<IRepository>(適切なタイプ名を挿入する)を入力して、それが注入された場所のどこにでも_repositoryの場所に注入するだけです。その後、戻り値を設定し、例外のためにメソッドをテストできます。

mockRepository.Setup(x => x.All<User>()).Returns(new List<User> { ... }); 
+1

いいえ:あなたのメソッドが正しいユーザーを返すかどうかもテストしています。 'GetUserById(" 4 ")'が明示的にテストしない限り、IDが "4"のユーザを返すことを保証するものは何もありません。リポジトリからのデータのみを返すと仮定した場合、10の 'Users'リポジトリを仮定すると、11通りの結果が得られます*。だから、もしあなたが完全にテストしているなら、十分にテストする必要があります。 –

2

通常、リポジトリレイヤに対して直接テストを書きません。 たとえば、nHibernateまたはEntity Frameworkを使用しているとします。これは、リポジトリに対する配線テストが技術的にそのフレームワークをテストしているからです。

クリエイターまたはそのORMは既に作成済みです。

また、データベースと会話することで、ユニットテストではなく統合テストが行​​われます。

ユニットテストは、たとえば、ビジネスレイヤーがレポジトリレイヤーを模倣してテストすることです。

統合テストを作成する場合は、ビジネスレイヤーに対してもそれを書きますが、リポジトリレイヤーをモックして通過させないでください。

+0

これは、リポジトリレイヤのテストに関するものではありません。 GetUserByIdメソッドのロジックが正しいことがテストされていますが、そうでない可能性があります。あなたは正しいのリポジトリの実装のボックスの外の実装を信じることができますが、それはあなたのコードが正しく使用されていることを意味するものではありません! –

+0

私はそれを言いました、それが私の答えを不明瞭にしていたら謝ります。私は、GetUserByIdがビジネス層のメソッドであると仮定しているので、正しいデータがメソッドによって返されたことを確認したい場合は、それに対して統合テストを作成します。テストでは、最初にテストデータをデータベースに挿入し、メソッドを実行してから、呼び出しによって期待値が返されることをアサートします。単体テストを書く場合は、単純にリポジトリレイヤをモックアウトして、モックされたオブジェクトのGetUserByIdが期待どおりに呼び出されていることを確認します。 – Nope

1

私はあなたのコードを準備するために、次の操作を行います:

  1. は確認してくださいあなたの_repositoryそれは簡単にテストのために変更することができるように、コンストラクタまたはプロパティを介して渡されています。
  2. _repository変数が具体的なタイプではなくIRepositoryタイプとして宣言されていることを確認してください。
  3. あなたのテストで続いて

、:

  1. は、あなたのインターフェースのモックを作成し、_repositoryになるこの中を渡します。
  2. .All<User>()メソッドをオーバーライドして、既知のハードコードされたリストUserをテストに適した値に戻します。
  3. 既存のIDを照会するときに正しい値が返されることを1つのテストでアサートします。
  4. 存在しないIDを照会するときに例外がスローされることを別個のテストで示します。
0

あなたはユニットテストのためにすべてを模擬する必要はありませんようRavenDBを具体的に設計されています。

メモリ内で実行するだけで、ユニットテストを直接実行できます。詳細はthis blog postを参照してください。

それは、あなたがこのようなコードを書くことができます:

[Fact] 
public void CanQueryForDistinctItemsUsingLinq() 
{ 
    using (var store = NewDocumentStore()) 
    { 
     using (var s = store.OpenSession()) 
     { 
      s.Store(new { Name = "ayende" }); 
      s.Store(new { Name = "ayende" }); 
      s.Store(new { Name = "rahien" }); 
      s.SaveChanges(); 
     } 

     store.DocumentDatabase.PutIndex("test", new IndexDefinition 
     { 
      Map = "from doc in docs select new { doc.Name }", 
      Stores = { { "Name", FieldStorage.Yes } } 
     }); 

     using (var s = store.OpenSession()) 
     { 
      var objects = s.Query<User>("test") 
       .Customize(x => x.WaitForNonStaleResults()) 
       .Select(o => new {o.Name }) 
       .Distinct() 
       .ToList(); 

      Assert.Equal(2, objects.Count); 
      Assert.Equal("ayende", objects[0].Name); 
      Assert.Equal("rahien", objects[1].Name); 
     } 
    } 
} 

これはRavenDB unit/integration testsから来ているので、あなたはそれが作業を取得するためにいくつかのinfasctuctureが必要になりますが、それは一般的なアイデアを提供します。

+0

ええ、しかし、なぜあなたは実際に物事(コントローラ、dbaseなど)全体をテストする統合テストを書くことができるときに、ユニットテストを書くために、モック、期待などを設定するのを迷う? –

+0

メモリ内にいれば、単にレイヴンがメモリ内の偽のDBを実行しているかどうかはわかりません。単体テストはすべての外部レイヤーをモックする必要がありますが、データベース、メモリまたはその他のデータストレージにデータを書き込むとすぐに単体テストではなく統合テストと見なされます。 – Nope

+0

@FrançoisWahlはAyendeのブログ記事のいくつかを見て、私が与えるよりもはるかに優れた説明をしています。 http://ayende.com/blog/153029/northwind-starter-kit-review-data-access-and-the-essence-of-needless-work-part-ii?key=01a97aa23ec049839c3fb2dd91421e61およびhttp:// ayendeを参照してください。 .com/blog/153701/ask-ayende-life-without-repositories-are-they-worth-living(初心者の方に) –

関連する問題