Question

I am just getting started with unit testing and now stuck writing a test method for delete. I am using MStest and JuckMock. I have my test method as follow. The idea is not to use real repository and use JustMock to mock one but in the code, i am getting a value for updatedCustomer and the test method failed. Hope someone can point out me the right direction.

    [TestMethod]
    public void ShouldDeleteCustomerWithIdParam()
    {
        var repo = Mock.Create<ICustomerRepository>();
        var customerService = new CustomerService(repo);
        var customer = Mock.Create<Customer>();            
        customerService.Delete(customer.Id);
        var updatedCustomer = _customerService.Get(customer.Id);
        Assert.IsNull(updatedCustomer, "customer hasn't been deleted");
    }
Was it helpful?

Solution

A short answer and a longer one :)

As pointed out by @Lilshieste, you're working with two different repository objects. Your customer object is deleted from one of them and then attempted to be retrieved from the other, possibly without ever being added to the other in the first place.

You may want to take another look at what you're testing here. Assuming CustomerService is a fairly thin wrapper around CustomerRepository, all this test would really do once it was complete is run code through CustomerService.Delete and check it calls CustomerRepository.Delete. The problem with this is two-fold:

  1. You're testing how a class does it's job, not what the class does. This couples the test to the class and requires the test to know things about CustomerService which are really none of its business.

  2. When this code runs without a mock, I assume you're using an ORM or ADO.NET to actually delete an item from your data store - that's the behaviour you want to be sure works, but you're mocking it out. Having a test which says "Deleting Customers works!" but which doesn't actually test the real customer deletion code could be deceptive.

With this in mind, I wouldn't say the test you're writing actually buys you very much. I'd recommend changing it to an integration test which actually hits your data store and exercises the real delete code.

Jimmy Bogard's written about unit testing repositories here.

OTHER TIPS

You could do it in two ways.

Assert that the relevant method on ICustomerRepository has been called. If it was called Delete then this would be:

Mock.Assert(() => repo.Delete(), Occurs.Once());

Or use a fake. Create FakeCustomerRepository implementing ICustomerRepository. Implement an add method to allow customers to be added and in your test set up customers in it. The delete method then just needs to remove that customer.

var repo = new FakeCustomerRepository();
repo.AddCustomer(1);
repo.AddCustomer(2);
var customerService = new CustomerService(repo); 
customerService.Delete(1);
var deletedCustomer = _customerService.Get(1);
Assert.IsNull(updatedCustomer, "customer hasn't been deleted");

Your test appears to be using two different CustomerServices: one created inside the test, customerService, and another created outside the test, _customerService.

Aside from that, since you want to mock out the repository it would be easier to just use behavior verification to assert the expected result. That is, you don't really want to perform a delete, and then try to retrieve the deleted customer - you just want to verify that customerService invokes the correct method on the supplied repository.

For example:

[TestMethod]
public void ShouldDeleteCustomerWithIdParam()
{
    var testID = "A test ID";
    var repo = Mock.Create<ICustomerRepository>();
    var customerService = new CustomerService(repo);
    customerService.Delete(testID);

    Mock.Assert(() => repo.DeleteCustomer(testID), Occurs.AtLeastOnce());
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top