Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a unit test perform double-duty by accepting a boolean value as a switch, or should I write two separate tests that duplicate the test code?

I have a method whose operations depend on its dependents, like below. Is it still value doing unit test? Because the unit test is not testing any business logic, rather by mocks.

Unit test below:

Please note that the method's opetions is determined by expectedCustomerValidality, which is setup by the test. Mostly, the logic is determined by mocks (e.g. Setup(c => c.IsValid()).

        [Test]
        [TestCase(true)]
        [TestCase(false)]
        public void AddCustomer(bool expectedCustomerValidality)
        {
           //using Moq
            companyRepositoryMock.Setup(c => c.GetById(It.IsAny<int>())).Returns(new Company());          
            customerValidatorMock.Setup(c => c.IsValid(It.IsAny<Customer>())).Returns(expectedCustomerValidality);

            var customer = new Customer
                               {
                                   Firstname = "firstName",
                                   Surname = "surname",
                                   Company = new Company { Id = 1 }
                               };

            var addCustomer = customerServiceSut.AddCustomer(customer);

            Assert.AreEqual(expectedCustomerValidality,addCustomer);
        }

Production code below:

 public class CustomerService : ICustomerService
    {
        private ICompanyRepository companyRepository;
        private ICustomerRepository customerRepository;
        private ICustomerValidator customerValidator;

        public CustomerService(ICompanyRepository companyRepository, ICustomerRepository customerRepository, ICustomerValidator customerValidator)
        {
            this.companyRepository = companyRepository;
            this.customerRepository = customerRepository;
            this.customerValidator = customerValidator;

        }

        public bool AddCustomer(Customer customer)
        {           
            customer.Company = companyRepository.GetById(customer.Company.Id); ;

            if (customerValidator.IsValid(customer))
            {
                customerRepository.AddCustomer(customer);

                return true;
            }

            return false;
        }
}

Questions:

  • Is AddCustomer() required unit-testing?
  • If so, is the current unit test performing the correct way?

    1 If not, what is the proper way to unit test it?

like image 415
Pingpong Avatar asked Jul 12 '13 02:07

Pingpong


1 Answers

I don't like this. Here's why: your test method names should reflect the method under test, what the preconditions of the test are, and what you expect the result of the test to be:

public bool AddCustomer_CustomerIsValid_ShouldReturnTrue()

public bool AddCustomer_CustomerIsInvalid_ShouldReturnFalse()

Now if you want to, you can refactor the core testing logic into its own method to eliminate the code duplication, and then call that method from the two above methods. But the refactored method is not a test case; it's just a helper method for the actual test cases.

Example:

[Test]
public void AddCustomer_CustomerIsValid_ShouldReturnTrue()
{
    var result = AddCustomerTest(true);
    Assert.IsTrue(result);
}

[Test]
public void AddCustomer_CustomerIsInvalid_ShouldReturnFalse()
{
    var result = AddCustomerTest(false);
    Assert.IsFalse(result);
}

public void AddCustomerTest(bool expectedCustomerValidality)
{
   //using Moq
    companyRepositoryMock.Setup(c => c.GetById(It.IsAny<int>())).Returns(new Company());          
    customerValidatorMock.Setup(c => c.IsValid(It.IsAny<Customer>())).Returns(expectedCustomerValidality);

    var customer = new Customer
    {
        Firstname = "firstName",
        Surname = "surname",
        Company = new Company { Id = 1 }
    };

    var result= customerServiceSut.AddCustomer(customer);

    return result;
}
like image 125
Robert Harvey Avatar answered Sep 21 '22 00:09

Robert Harvey