C# 测试成功时重定向的控制器方法-moq

C# 测试成功时重定向的控制器方法-moq,c#,unit-testing,moq,C#,Unit Testing,Moq,让我们采取以下措施: mockSiteRepository.Setup(m => m.Sites).Returns(new Site[] { new Site { SiteID = 0, DateCreated = DateTime.Now, Name = "A", AddressID = 0 }

让我们采取以下措施:

        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);
现在看一下编辑方法(伪):

你如何测试这种方法

成功后,它重定向到“列表”控制器,该控制器返回ViewResult。我不想仅仅因为它已重定向而相信它,我的数据已成功编辑和保存


那么,当我将SiteViewModel放入控制器方法中时,如何检查它是否确实成功编辑了现有站点。

使用
mockbehavior.Strict
创建
mockSiteRepository
mockAddressRepository

当您运行测试时,您应该会看到一个异常,该异常表示您调用IAddressRepository.Edit(Site)失败,MockBehavior.Strict。现在您确切地知道在存储库中调用了哪些方法,这样您就知道它确实编辑了站点

然后你必须通过测试。在测试中设置模拟存储库以期望编辑。您不知道
站点
地址
的哪个实例将被传递到您的模拟存储库,因此您必须使用It.is方法来允许任何匹配实例。差不多

mockSiteRepository.Setup(repo => repo.Save(It.Is<Site>(s => s.SiteID == testForm.SiteID)));
mockSiteRepository.Setup(repo=>repo.Save(It.Is(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();
//排列
var mockSiteRepository=new Mock();
var testForm=新站点{SiteID=0};
Site savedSite=null;
mockSiteRepository
.Setup(repo=>repo.Save(It.IsAny()))
.Callback(s=>savedSite=s);
//表演
var controller=新站点控制器(mockChemical.Object、mockSiteRepository.Object、mockChemicalRelationRepository.Object、mockAddressRepository.Object);
var结果=controller.Edit(testForm);
//断言
Assert.That(savedSite,Is.Not.Null)//这将验证是否调用了安装程序
Assert.That(savedSite.SiteID,Is.EqualTo(testForm.SiteID));
Assert.That(savedSite.Name,Is.EqualTo(testForm.Name));
//你还有其他主张吗
//始终在最后验证所有设置,以便您知道所有设置都已调用
mockSiteRepository.VerifyAll();

那么您要检查的是什么?是否调用了repository Edit()方法?如果能使用我的addressRepository.Edit(地址)和siteRepository.Edit(站点)正确修改我最初从mockSiteRepository/mockAddressRepository获得的假模型,那就太好了;我可以通过断言新的存储库模型将等同于testForm SiteViewModel来测试这一点。也许这比我原来想的要复杂得多?我会尽快尝试的。谢谢你的时间,兄弟!别担心,让我知道你进展如何。@JoeTaylor虽然不适用于你的场景,但值得一提的是,有时你可能需要
设置
模拟的各种方法来支持被测试的类,但你不一定要验证它们是否都被调用了。因此,您不必使用
.VerifyAll
,而可以
。验证
特定的方法和属性,查看它们是否被访问(甚至被访问了多少次)。我脑海中浮现出类似于
mockSiteRepository.Verify(repo=>repo.Save(It.IsAny())、Times.Once()的东西。@AndrewStephens我完全同意,尤其是当您在多个测试用例之间使用共享
设置
方法时。对我来说,它归结为如何使阅读者尽可能清楚地理解测试的意图,而不引入重复。
//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();