【问题标题】:Testing a controller method that redirects on success - moq测试成功重定向的控制器方法 - moq
【发布时间】:2014-03-06 15:49:33
【问题描述】:

让我们采取以下措施:

        mockSiteRepository.Setup(m => m.Sites).Returns(new Site[] {
            new Site {
                SiteID = 0,
                DateCreated = DateTime.Now,
                Name = "A",
                AddressID = 0
            }
        }.AsQueryable());

        mockAddressRepository.Setup(m => m.Addresses).Returns(new Address[] {
            new Address {
                AddressID = 0,
                Address1 = "A",
                Address2 = "B",
                CityID = 0,
                CountryID = 0,
                StateID = 0,
                ZIP = "D"
            }
        }.AsQueryable());

        SiteViewModel testForm = new SiteViewModel
        {
            SiteID = 0,
            DateCreated = DateTime.Now,
            Name = "A",
            AddressID = 0,
            Address1 = "E",
            Address2 = "F",
            CityID = 0,
            City = null,
            CountryID = 0,
            Country = null,
            StateID = 0,
            State = null,
            ZIP = "J"
        };


        SiteController controller = new SiteController(mockChemical.Object, mockSiteRepository.Object, mockChemicalRelationRepository.Object, mockAddressRepository.Object);

        ActionResult result = controller.Edit(testForm);

现在看看Edit方法(伪):

    public ActionResult Edit(SiteViewModel siteViewModel)
    {
        if (ModelState.IsValid)
        {
            Address address = siteViewModel.Map();
            addressRepository.Edit(address);
            Site site = siteViewModel.Map(address.AddressID);
            siteRepository.Edit(site);

            TempData["success"] = string.Format("Site {0} was successfully edited", site.Name);
            return RedirectToAction("List");
        }
        else
        {
            // Something wrong with the values
        }
        return View(siteViewModel);
    }

您如何测试这种方法?

成功时,它会重定向到返回 ViewResult 的“List”控制器。我不想仅仅因为它已重定向就相信我的数据已成功编辑和保存...

那么我可以做些什么来检查,当我将 SiteViewModel 放入我的控制器方法时,它确实成功地编辑了现有网站。

【问题讨论】:

  • 那么您要检查的是什么?存储库的 Edit() 方法是否已被调用?
  • 很高兴看到我最初从 mockSiteRepository/mockAddressRepository 获得的假模型是否已使用我的 addressRepository.Edit(address) 和 siteRepository.Edit(site) 正确修改;我可以通过断言新的存储库模型等于 testForm SiteViewModel 来测试它。也许它比我最初想象的要复杂得多?

标签: c# unit-testing moq


【解决方案1】:

在创建mockSiteRepository 和mockAddressRepository 时使用MockBehaviour.Strict。

当您运行测试时,您应该会看到一个显示您的invocation of IAddressRepository.Edit(Site) failed with MockBehaviour.Strict 的异常。现在您确切地知道在您的存储库上调用了哪些方法,因此您将知道它确实编辑了该站点。

然后你必须让测试通过。在您的测试中设置模拟存储库以期待编辑。您不确切知道 Site 或 Address 的哪个实例将被传递到您的模拟存储库,因此您必须使用 It.Is 方法来允许任何匹配的实例。类似的东西

mockSiteRepository.Setup(repo => repo.Save(It.Is<Site>(s => s.SiteID == testForm.SiteID)));

这样您就可以验证传递到存储库的内容是否至少具有正确的 ID。


解决这个问题的另一种方法是使用 It.IsAny 方法,将站点分配给测试方法中的局部变量,然后在之后断言它。我发现这会导致更多不言自明的错误消息和更容易调试。例如:

//arrange
var mockSiteRepository = new Mock<ISiteRepository>();
var testForm = new Site { SiteID = 0 };

Site savedSite = null;
mockSiteRepository
    .Setup(repo => repo.Save(It.IsAny<Site>()))
    .Callback<Site>(s => savedSite = s);

//act
var controller = new SiteController(mockChemical.Object, mockSiteRepository.Object, mockChemicalRelationRepository.Object, mockAddressRepository.Object);
var result = controller.Edit(testForm);

//assert
Assert.That(savedSite, Is.Not.Null); //this verifies that your setup was called
Assert.That(savedSite.SiteID, Is.EqualTo(testForm.SiteID));
Assert.That(savedSite.Name, Is.EqualTo(testForm.Name));

//do your other asserts

//always VerifyAll at the end so you know your setups were all called
mockSiteRepository.VerifyAll();

【讨论】:

  • 我会尽快尝试一下。感谢您的宝贵时间!
  • 别担心,让我知道你的进展情况。
  • @JoeTaylor 虽然不适用于您的场景,但值得一提的是,有时您可能需要 Setup 模拟的各种方法来支持正在测试的类,但您不一定要验证他们被全部调用。因此,您可以使用.Verify 特定的方法和属性来查看它们是否被访问(甚至访问了多少次),而不是使用.VerifyAll。例如mockSiteRepository.Verify(repo =&gt; repo.Save(It.IsAny&lt;Site&gt;()), Times.Once());之类的东西。
  • @AndrewStephens 我完全同意,特别是如果您在多个测试用例之间使用共享的SetUp 方法。对我来说,这归结为如何让正在阅读它的人尽可能清楚地了解测试的意图,而不引入重复。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-03
  • 1970-01-01
  • 2014-02-28
  • 1970-01-01
相关资源
最近更新 更多