简体   繁体   中英

Moq test if an attribute was changed in a method that returns void

I'd like to know if its possible to test, using Moq, if some attribute in an object was changed by some method, that method must be void.

i want to check if the attribute "FlgActive" of product was changed from true to false.

the delete method is void, and it just change that flag to false.

if its possible, what should i add to my setup to check that ?

Example:

TEST

[TestMethod]
    public void DeletedProductFlagShouldBeFalse() //RN03
    {
        var product = new Product() { Id = 1, Name = "aaaaaa", Code = "aaaaaa", FlgActive = true };
        var so = new ServiceOrder() {  };

        var mockProductRepository = new Mock<IProductRepository>();
        mockProductRepository.Setup(p => p.Delete(product));

        var mockServiceOrderRepository = new Mock<IServiceOrderRepository>();
        mockServiceOrderRepository.Setup(o => o.GetProductById(product.Id)).Returns(new List<ServiceOrder> { so });

        var service = new ProductService(mockProductRepository.Object, mockServiceOrderRepository.Object);

        service.Delete(product);

        mockProductRepository.Verify(c => c.Delete(It.IsAny<Product>()), Times.Once());
        mockProductRepository.Verify((s => s.Commit()), Times.Once());

        Assert.IsFalse(product.FlgActive);
    }

SERVICE

public void Delete(Product product)
    {
        Validate(product);
        repo.Delete(product);
        repo.Commit();
    }

REPOSITORY

public void Delete(Product product)
    {
        try
        {
            product.FlgActive = false;
            Update(product);
        }
        catch (Exception ex)
        {
            throw new Exception(ex.Message, ex);
        }
    }

It is not your service which is setting the flag to false, so you should not test that behavior from your service. The job of this unit is to validate the product, then delegate the deletion to the repository.

So you can remove that part from your test and rename it:

[TestMethod]
public void DeletionShouldBeSentToRepository() //RN03
{
    var product = new Product() { Id = 1, Name = "aaaaaa", Code = "aaaaaa", FlgActive = true };
    var so = new ServiceOrder() {  };

    var mockProductRepository = new Mock<IProductRepository>();
    mockProductRepository.Setup(p => p.Delete(product));

    var mockServiceOrderRepository = new Mock<IServiceOrderRepository>();
    mockServiceOrderRepository.Setup(o => o.GetProductById(product.Id)).Returns(new List<ServiceOrder> { so });

    var service = new ProductService(mockProductRepository.Object, mockServiceOrderRepository.Object);

    service.Delete(product);

    mockProductRepository.Verify(c => c.Delete(product), Times.Once());
    mockProductRepository.Verify((s => s.Commit()), Times.Once());
}

NOTE : I's good to verify we're sending the good product to the repo. I've replaced your It.IsAny with the product you created previously.

Now that we covered the duties of your service, we can test the deletion behavior into the repo itself, which should look like this:

[TestMethod]
public void DeletedProductFlagShouldBeFalse() //RN03
{
    var product = new Product() { Id = 1, Name = "aaaaaa", Code = "aaaaaa", FlgActive = true };

    IProductRepository repository = new ProductRepository();

    repository.Delete(product);

    Assert.IsFalse(product.FlgActive);
}

When you're doing unit tests, it's important to test only the behavior of the current class, not the side effects.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM