具有依赖注入服务和存储库的单元测试控制器

时间:2012-03-14 21:11:40

标签: unit-testing ninject moq

我有一个非常标准的.NET MVC 3应用程序,它使用Ninject进行依赖注入。我正在尝试进行单元测试的是从控制器返回的视图。有一个控制器上有一个组服务,该服务有一个存储库。该服务首先检查该组是否存在,如果存在,则返回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");
   }
}

服务

[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);
}

我要测试的是,当我添加一个组时,它应该可以工作,然后当我添加相同的组时,它应该转到另一个视图。但是现在,单元测试使用真实存储库而不是模拟存储库。如何使模拟服务上的存储库由单元测试控制而不是实际使用真实存储库?

2 个答案:

答案 0 :(得分:2)

如果您正在对Controller进行单元测试,那么您无需担心存储库,因为您的服务是模拟的。就控制器而言,没有存储库,它所知道的只是IGroupService合同。

根据您提供的代码,我无法看到您的睾丸如何使用真实存储库。如果您想更改测试的结果,则需要为IGroupService模拟提供一些模拟响应。

您需要为接受Mocked Repository的GroupService进行第二次单元测试。

  

IMO单元测试应该只测试一个类,其他一切   应该被嘲笑或者是非常简单的dto对象。如果你是   做得更多然后是集成测试。

答案 1 :(得分:0)

鉴于Bronumski的建议,我最终简化了一下。这是代码,所有似乎都运行良好。

        [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);
    }