user4903
user4903

Reputation:

Is it correct to test all of the possible conditions or states of an object returned from a unit?

Imagine unit testing the following sample scenario. Let's say I've mocked out the CustomerDAO in order to return a valid customer and customer orders. Testing this scenario is fairly easy. Except when I get to testing the boolean for whether or not a customer has orders. In some real world scenarios they will not have orders. So do I need to add some condition in my mock DAO that will return a customer with no orders, and then test that as well? Now imagine it is much more complicated and there are several pieces of the DTO that could contain various bits of information depending on the real results coming back from the database. Do I need to test all of those various conditions?

public class Manager {

    public CustomerDTO getCustomerInformation() {

        CustomerDAO customerDAO = new CustomerDAO();

        CustomerDTO customerDTO = new CustomerDTO();
        customerDTO.setCustomer(customerDAO.getCustomer(1));
        customerDTO.setCustomerOrders(customerDAO.getCustomerOrders(1));
        if (!customerDTO.getCustomerOrders.isEmpty()) {
            customerDTO.setHasCustomerOrders(true);
        }

        return customerDTO;
    }
}

Upvotes: 1

Views: 66

Answers (2)

Piotr Perak
Piotr Perak

Reputation: 11088

You want to test if Manager is converting Customer and it's related data to CustomerDTO. So yes you have to test all those different scenarios. But don't do it all in one test. Each test should reach it's end either finishing with success or failure. What I mean:


// Don't do this
[Test]
public void Manager_Converts_Customer_to_CustomerDTO()
{
  // mock setup
  var dto = Manager.GetCustomer();

  Assert.That(dto, Is.Not.Null);
  Assert.That(dto.Firstname, Is.EqualTo("what has been setup in mock"));
  Assert.That(dto.Orders.Count, Is.EqualTo(expected_set_in_mock));
  Assert.That(dto.Orders[0].Product, Is.EqualTo(expected_set_in_mock_product));
}

Because then you have one test failing when there is one error and when there are 4 errors. You fix one bug and expect test to pass but then it fails again on next line. Put that all asserts in different tests with describing names.

Upvotes: 1

Sam Holder
Sam Holder

Reputation: 32936

In short, I think yes you should test that when the DAO returns various things that the expected state exists on the DTO. Otherwise how can you have an confidence that the DTO will be an accurate representation of the data that was in the datastore?

You should create either a mock DAO per test with the required data for the test, or a mock DAO for each state that needs to be tested.

I'd probably have tests like:

CustomerHasOrders_WhenDaoReturnsNoOrders_ReturnsFalse

CustomerHasOrders_WhenDaoReturnsOrders_ReturnsTrue

GetCustomer_WhenDaoReturnsCustomer_CustomerIsSame

GetCustomerOrders_WhenDaoReturnsOrders_OrdersAreTheSame

GetCustomerOrders_WhenDaoReturnsNoOrders_OrdersAreEmpty

and then tests for what happens if any of the calls to the Dao fail...

In this example it seems that the flag is redundant in the DTO, as it is just different representations of other data. You could implement that as an extension method on CustomerDTO, or some logic in the setCustomerOrders. If the DTO is to be sent over the wire and the functionality won't neccessarily be there then you could exclude the property and the client could just do the check to see if there are any orders in the same way you are customerDTO.getCustomerOrders.isEmpty()

Upvotes: 1

Related Questions