2012-03-14 6 views
0

依存性注入にNinjectを使用するかなり標準的な.NET MVC 3アプリケーションがあります。私が単体テストしようとしているのは、コントローラから返されるビューです。そこにグループサービスを持つコントローラがあり、サービスはリポジトリを持っています。サービスはまず、そのグループが存在するかどうかを調べ、グループが存在する場合は、エラーと共にfalseを返します。次に、ブール値をチェックして、ユーザーをグループのリストに移動するか、現在のページに留まり、値を表示するかを決定します。依存性注入サービスとリポジトリを持つユニットテストコントローラ

コントローラ

[HttpPost] 
public ActionResult AddGroup(Group g) 
{ 
    string error = string.Empty; 
    if (groupService.Save(g, CurrentUser, out error)) 
    { 
     return RedirectToAction("GetGroups"); 
    } 
    else 
    { 
     ViewData["Error"] = error; 
     return View("AddGroup"); 
    } 
} 

私は、TEにしようとしているどのようなサービス

[Inject] 
public IGroupRepository CurrentGroupRepo { get; set; } 

public bool Save(Group group, string username, out string error) 
{ 
    error = string.Empty; 
    var found = CurrentGroupRepo.GetGroup(group.Descr, false); 
    if (found != null) 
    { 
     error = "That group alread exists"; 
     return false; 
    } 

    if (group.CreatedBy == null || group.CreatedBy == string.Empty) 
    { 
     group.CreatedBy = username; 
     group.CreatedOn = DateTime.Now; 
     group.IsDeleted =false; 
    } 

    group.ModifiedBy = username; 
    group.ModifiedOn = DateTime.Now; 

    try 
    { 
     if (group.GroupID == 0) 
     { 
      CurrentGroupRepo.AddGroup(group); 
     } 
     else 
     { 
      CurrentGroupRepo.UpdateGroup(group); 
     } 
     return true; 
    } 
    catch (Exception ex) 
    { 
     error = ex.Message + ex.StackTrace; 
     return false; 
    } 
} 

ユニットテスト

[TestMethod] 
public void TestAddGroup() 
{ 
    // Arrange 
    Mock<IUserService> uService = new Mock<IUserService>(); 
    Mock<IGroupService> gService = new Mock<IGroupService>(); 
    Mock<IObservationService> oService = new Mock<IObservationService>(); 
    Mock<IGroupRepository> mockGroupRepo = new Mock<IGroupRepository>(); 

     string error = string.Empty; 
     List<Group> groups = new List<Group>(); 
     Group newGroup = new Group() { Descr = "Test Group 1234566", IsDeleted = false }; 
     Mock<IGroupRepository> mockGroupRepo = new Mock<IGroupRepository>(); 

     mockGroupRepo.Setup(cr => cr.GetGroups(It.IsAny<bool>())).Returns(
      delegate { 
       return groups; 
      }); 
     mockGroupRepo.Setup(cr => cr.GetGroup(It.IsAny<string>(), It.IsAny<bool>())).Returns(
      delegate(Group _group) { 
       return groups.Where(f => f.Descr == _group.Descr).FirstOrDefault(); 
      }); 
     mockGroupRepo.Setup(cr => cr.AddGroup(newGroup)).Returns(
      delegate { 
       groups.Add(newGroup); 
       return newGroup; 
      }); 
     gService.SetupGet(d => d.CurrentGroupRepo).Returns(mockGroupRepo.Object); 


    AdminController controller = new AdminController(gService.Object, uService.Object, oService.Object); 
    Group newGroup = new Group() { Descr = "Test Group 1234566", IsDeleted = false }; 
    var success = (ViewResult)controller.AddGroup(newGroup); 
    Assert.IsTrue("GetGroups" == success.ViewName); 

    var failure = (ViewResult)controller.AddGroup(newGroup); 
    Assert.IsTrue("AddGroup" == failure.ViewName); 
} 

私が1つのグループを追加すると、そのグループが機能するはずです。同じグループを追加すると、別のグループに移動する必要があります。しかし、今は単体テストは嘲笑されたものの代わりに実際のリポジトリを使用しています。実際のリポジトリを実際に使用するのではなく、ユニットテストによって制御されるように、模擬サービス上のリポジトリを取得するにはどうすればよいですか?

答えて

2

コントローラを単体テストする場合、サービスが偽装されているため、リポジトリについて心配する必要はありません。コントローラに関する限り、リポジトリは存在しません。IGroupService契約があれば知っているだけです。

あなたが提供したコードでは、あなたのtestisが実際のリポジトリをどのように使用しているかわかりません。テストの結果を変更したいのであれば、あなたのIGroupServiceモックへの嘲笑い反応を提供する必要があります。

Mocked Repositoryを使用するGroupServiceの2番目のユニットテストが必要です。

IMO単体テストは1つのクラスのみをテストする必要があります。それ以外のものはすべて嘲笑されるか、非常に単純なオブジェクトにする必要があります。 より多くのことをしているのであれば、それは統合テストです。

+0

単体テスト内のコレクションではなくデータベースに保存し続けるため、非常に簡単なことがあります。私は手動でリポジトリを設定してモックサービスに配置することを示すためにテストを更新しましたが、デリゲートは決して呼び出されません。 NinjectModuleを使用して単体テスト用のモックに新しいバインディングを作成するDefaultModuleを作成する必要がありますか? – Josh

+0

@Josh私はninjectの専門家ではありません。私はウィンザーを使用しますが、コンセプトは同じでなければなりません。私が見ることで、コントローラがリポジトリを使用しないので、リポジトリをモックアウトする必要はありません。実際、あなたのIoCは単体テストレベルでは関連してはいけません。あなたは単体テストワイヤーからすべてを見せていますか?あなたが見せていない設定はありますか? – Bronumski

+0

あなたの答えは正しい方向に向いていました。私はフォローアップを投稿します。 – Josh

0

私は、ブロンマスキーのアドバイスを少し簡略化しました。ここにコードがあり、すべてがうまく機能しているようです。

 [TestMethod] 
    public void TestAddGroup() { 
     // Arrange 
     Group newGroup = new Group() { Descr = "Test Group 1234566", IsDeleted = false }; 
     gService.Setup(cr => cr.Save(It.IsAny<Group>(), It.IsAny<string>())).Returns(""); 

     AdminController controller = new AdminController(gService.Object, uService.Object, oService.Object); 

     // Act 
     var success = (RedirectToRouteResult)controller.AddGroup(newGroup); 
     Assert.IsTrue("GetGroups" == success.RouteValues["action"].ToString()); 

     gService.Setup(cr => cr.Save(It.IsAny<Group>(), It.IsAny<string>())).Returns("Error"); 
     var failure = (ViewResult)controller.AddGroup(newGroup); 
     Assert.IsTrue("AddGroup" == failure.ViewName); 
    }