How reliable is check () in Moq?

I am only new to Unit Testing and ASP.NET MVC. I am trying to figure out how to use Steve Sanderson "Pro ASP.NET MVC Framework". The book has this piece of code:

public class AdminController : Controller { ... [AcceptVerbs(HttpVerbs.Post)] public ActionResult Edit(Product product, HttpPostedFileBase image) { ... productsRepository.SaveProduct(product); TempData["message"] = product.Name + " has been saved."; return RedirectToAction("Index"); } } 

What he feels like this:

 [Test] public void Edit_Action_Saves_Product_To_Repository_And_Redirects_To_Index() { // Arrange AdminController controller = new AdminController(mockRepos.Object); Product newProduct = new Product(); // Act var result = (RedirectToRouteResult)controller.Edit(newProduct, null); // Assert: Saved product to repository and redirected mockRepos.Verify(x => x.SaveProduct(newProduct)); Assert.AreEqual("Index", result.RouteValues["action"]); } 

TEST VIEW.

Therefore, I intentionally distort the code by adding "productsRepository.DeleteProduct (product)"; after "SaveProduct (product)"; how in:

  ... productsRepository.SaveProduct(product); productsRepository.DeleteProduct(product); ... 

TEST TEST (i.e. condominates a catastrophic [hypnosis + intuition] -induced typo :))

Could this test be written better? Or is there something I should know? Many thanks.

+4
source share
4 answers

I think that you may misinterpret the purpose of .Verify ().

It checks that this method has been called with the expected value.

On page 187 of the book, Steve says: β€œNotice how he uses the Moqs.Verify () method to ensure that AdminController actually called DeleteProduct () with the correct parameter. '

So, in your case, the test passes because it is just a call test, not a functionality.

As TDD Follows the Book, Addendum

 productsRepository.DeleteProduct(product); 

should first add to test

 // Assert: Saved product to repository, then deleted and redirected mockRepos.Verify(x => x.SaveProduct(newProduct)) mockRepos.Verify(x => x.DeleteProduct(newProduct)); Assert.AreEqual("Index", result.RouteValues["action"]); 

and then added to code

 [AcceptVerbs(HttpVerbs.Post)] public ActionResult Edit(Product product, HttpPostedFileBase image) { ... productsRepository.SaveProduct(product); productsRepository.DeleteProduct(product); ... 
+7
source

As others have said, the test passes because your statement:

 mockRepos.Verify(x => x.SaveProduct(newProduct)); 

performed. Your code really called the SaveProduct method.

The Mock.Verify () method cannot check if any other method is called, what do you expect from it.

If you are worried about something strange (for example, how Delete () is called after Save ()) and want to prevent it with a test, you also need to add Verify () for this condition. Sort of:

 mockRepos.Verify(x => x.DeleteProduct(newProduct), Times.Never()); 
+4
source

Your intentional "corruption" of the code does not break the test, as you did after the call to which you Verify() before SaveProduct() . I always found Moq Verify() very reliable.

Some psuedo code for a more robust test might have your repository implement an interface and have a simple in-memory test version

 // Arrange var repo = SetupTestableRepository() var product = CreateProduct(productId) // Act repo.SaveProduct(product) // Assert Assert.IsNotNull(repo.Fetch(productId)) 

Kindness,

Dan

+2
source

The idea is to "write the simplest code that works." This will help you avoid stupid things, such as deleting files from disk when running the increment counter. Obviously, deleting files is easier.

0
source

Source: https://habr.com/ru/post/1306336/


All Articles