Насколько надежен Verify () в Moq? - PullRequest
4 голосов
/ 08 апреля 2010

Я только новичок в модульном тестировании и ASP.NET MVC. Я пытался разобраться с обоими, используя «Pro ASP.NET MVC Framework» Стива Сандерсона. В книге есть этот кусок кода:

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

Что он проверяет так:

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

ИСПЫТАНИЯ.

Поэтому я намеренно испортил код, добавив «productsRepository.DeleteProduct (product);» после «СохранитьПродукт (товар)»; как в:

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

ИСПЫТАНИЯ ИСПЫТАНИЙ. (То есть, оправдывает провоцирующую [гипноз + интеллигенция] опечатку :))

Может ли этот тест быть написан лучше? Или я должен кое-что знать? Большое спасибо.

Ответы [ 4 ]

7 голосов
/ 08 апреля 2010

Я думаю, что вы, возможно, неправильно истолковываете цель методов .Verify ().

Он проверяет, что данный метод был вызван с ожидаемым значением.

На странице 187 книги Стив говорит' Обратите внимание, как он использует метод Moqs .Verify (), чтобы убедиться, что AdminController действительно вызвал DeleteProduct () с правильным параметром. '

Так что в вашем случае тест проходит как онэто просто проверка вызова, а не функциональность.

Поскольку в ходе работы с книгой следят за TDD, сначала необходимо добавить

productsRepository.DeleteProduct(product);

к тесту

// 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"]);

, а затем добавляется к коду

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Product product, HttpPostedFileBase image)
{

     ...
productsRepository.SaveProduct(product);
productsRepository.DeleteProduct(product);
    ...
4 голосов
/ 08 апреля 2010

Как уже говорили другие, тест проходит, потому что ваше утверждение:

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

было выполнено. Ваш код сделал вызов метода SaveProduct.

Метод Mock.Verify () не может проверить, что какой-то другой метод не был вызван , что вы ожидаете от него.

Если вы беспокоитесь о том, что происходит что-то странное (например, Delete () вызывается после Save ()) и хотите предотвратить это с помощью теста, вам также необходимо добавить Verify () для этого условия. Что-то вроде:

mockRepos.Verify(x => x.DeleteProduct(newProduct), Times.Never());
2 голосов
/ 08 апреля 2010

Ваше преднамеренное «повреждение» кода не нарушает тест, как вы сделали это после вызова, который вы Verify() на SaveProduct(). Я всегда считал Moq's Verify() очень надежным.

Некоторым psuedo-кодом для более надежного теста может быть то, что ваш репозиторий реализует интерфейс и имеет простую тестируемую в памяти версию

// Arrange

var repo = SetupTestableRepository() 
var product = CreateProduct(productId)

// Act 
repo.SaveProduct(product)

// Assert
Assert.IsNotNull(repo.Fetch(productId))

Доброжелательность,

Dan

0 голосов
/ 08 апреля 2010

Идея состоит в том, чтобы «написать самый простой код, который работает».Это поможет вам избежать глупостей, таких как удаление файлов с диска с помощью счетчика приращений.Очевидно, что не удалять файлы проще.

...