Can a unit test do double work by taking a boolean as a switch, or do I need to write two separate tests that duplicate the test code?

I have a method whose operations depend on its dependents, as shown below. Is the unit test still doing the value? Because unit test does not test any business logic, but rather because of mocks.

Unit test below:

Note that the opetions method is determined by expectedCustomerValidality , which is set up by the test. Basically, logic is defined through 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 unit testing AddCustomer () required?
  • If so, is the current unit test the correct path?

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

+6
source share
2 answers

I do not like it. Here's why: your test method names should reflect the test method, what are the prerequisites for the test and what do you expect from the test result:

 public bool AddCustomer_CustomerIsValid_ShouldReturnTrue() public bool AddCustomer_CustomerIsInvalid_ShouldReturnFalse() 

Now, if you want, you can reorganize the core testing logic into your own method to eliminate code duplication, and then call this method from the two methods above. But the refactored method is not a test; it's just a helper method for real 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; } 
+7
source

AddCustomer requires testing because it executes business logic - it extracts the company and installs it, it checks the data, adds data to the repository and returns the result.

Your test is almost correct. I would make it a little more specific in order to test all the business logic:

 [Test] [TestCase(true)] [TestCase(false)] public void AddCustomer(bool isCustomerValid) { //arrange //NOTE!!! create the mocks with MockBehavior.Strict //that way the test will fail if a call is made w/o setup const long testCompanyId = 100; var testCompany = new Company{ Id = testCompanyId }; companyRepository.Setup(r => r.GetById(testCompanyId)) .Returns(testCompany); var testCustomer = new Customer { Firstname = "firstName", Surname = "surname", Company = new Company { Id = testCompanyId } }; customerValidatorMock.Setup(c => c.IsValid(It.Is<Customer>(c => c == testCustomer && c.Company == testCompany)).Returns(isCustomerValid); if (isCustomerValid) { customerRepository.Setup( r => r.AddCustomer(testCustomer) ). Verifiable(); } //act var addCustomerResult = customerServiceSut.AddCustomer(testCustomer); //assert Assert.AreEqual(isCustomerValid, addCustomerResult); cutomerRepository.VerifyAll(); } 

In the above test, all the functionality of the service method will be checked, including if the company is selected by identifier, and if the extracted one is used. In addition, it checks if the client has been added, if it is valid. The test will fail if the client is added, if it is invalid (since the Repository client was created using MockBehavior.Strict, and the configuration will not be completed).

0
source

Source: https://habr.com/ru/post/949280/


All Articles