سؤال

Let's take the following:

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

Now take a look at the Edit method (pseudo):

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

How do you go about testing such a method?

On success, it redirects to the "List" controller which returns a ViewResult. I don't want to trust that just because it has redirected, my data was successfully edited and saved...

so what can I do to check that, when I put a SiteViewModel into my controller method, it does indeed successfully edit the existing site.

لا يوجد حل صحيح

نصائح أخرى

Use MockBehaviour.Strict when you create your mockSiteRepository and mockAddressRepository.

When you run your test, you should see an exception that says your invocation of IAddressRepository.Edit(Site) failed with MockBehaviour.Strict. Now you know exactly what methods are being called on your repository, so you will know that it has indeed edited the site.

Then you have to make the tests pass. Setup the mock repositories in your test to expect the edit. You don't know exactly which instance of Site or Address is going to be passed to your mock repository so you have to use the It.Is<T> method to allow any matching instance. Something like

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

that way you verify that what's being passed to the repository at least has the right ID.


Another way to approach this, that I find a bit more robust, is to use the It.IsAny<T> method, assign the site to a local variable in the test method, and then Assert about it afterwards. I find this leads to more self-explanatory error messages and easier debugging. For instance:

//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();
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top