Developing Service layer by following TDD approach

Testing service layer in isolation: -

In previous chapter we learn how to write test cases for Controllers. So, after writing Controller Test Case, below scenario will happen.
– Controller test case fails as no controller implementation available
– So, we will write the controller code such that minimum test case passes.
– Controller needs Service class also. Since Service class is not yet written, write the Service layer.


So, in TDD, we will follow below steps: -
-- Before writing Service Class write the Test Case class. To do so, we will use Annotations:
@Mock
@InjectMock

Web Layer
(CustomerController)

Service Layer
(CustomerServiceImpl)

CustomerRepository
(Not implemented Yet)

As shown above Repository Layer is also not yet ready but we can proceed as below:
1. We can write and test our Service layer code without wiring in our complete persistence layer.
2. To complete this, we can practice the mocking provision provided by Spring Boot Test.

@Mock
CustomerRepository customerRepo;
@InjectMocks
private CustomerServiceImpl custService = new CustomerServiceImpl ();

@mock annotation on any object will enable you to set its behavior.
@InjectMocks creates an instance of the class and injects the mocks that are created with the @Mock (or @Spy) annotations into this instance.


Test case class for CustomerService : Mock all objects needed: -

@RunWith(SpringJUnit4ClassRunner.class)
@AutoConfigureMockMvc
@SpringBootTest
public class TestCustomerService {
@Mock
CustomerRepository customerRepo;
@Mock
PhoneSequence phSequence;
@Mock
PhoneSequenceRepository phRepo;
@Mock
ExtUtil util;

//Injects all mocks to CustomerServiceImp
@InjectMocks
CustomerServiceImpl custService;

//Other Pojos needed
static CustomerDTO custDTO;
static Customer cust;

//Setting Exception Rule
@Rule
public ExpectedException expectedException = ExpectedException.none();

Test case class for CustomerService :Set up the fixtures: -
@BeforeClass
public static void initialise() {
custDTO = new CustomerDTO();
cust = new Customer(); 
}

@Before
public void init() {
MockitoAnnotations.initMocks(this);
custDTO.setSsnId("123456789010");
custDTO.setAddress("#25, Millers Road, Bangalore");
custDTO.setDob("1981-03-20");
custDTO.setEmailId("Robert_Smith@gmail.com");
custDTO.setFirstName("Robert");
custDTO.setLastName("Smith");
}

@After
public void tearDown() {
customerRepo.deleteAll();
phRepo.deleteAll(); 
}
}

Testing updateCustomer() method of CustomerService class [Positive test case]: -

@Test
public void testUpdateCustomerPositive() throws CustomerException {
cust = CustomerDTO.prepareEntity(custDTO);
cust.setPhoneNo("9876536750");
custDTO.setPhoneNo("9876536750");
custDTO.setAddress("Jubilee Hills, Hyderabad");

//Training the mock objects
Mockito.when(customerRepo.saveAndFlush(cust)).thenReturn(cust);
Mockito.when(customerRepo.findByPhoneNo(Mockito.eq("9876536750"))).thenReturn(cust);

//Making the actual call
custService.updateCustomer("9876536750", "JubileeHills, Hyderabad");

//Verifying if the calls were made or not
Mockito.verify(customerRepo).findByPhoneNo(Mockito.eq("9876536750"));
try {
Mockito.verify(customerRepo).saveAndFlush(Mockito.any(Customer.class));
} catch (AssertionError e) {
}

}


Testing updateCustomer() method of CustomerService class [Negative test case]: -

@Test(expected = CustomerException.class)
public void testUpdateCustomerInvalidPhoneNo() throws CustomerException {
cust = CustomerDTO.prepareEntity(custDTO);
cust.setPhoneNo("9876536750");
custDTO.setPhoneNo("9876536750");

//Setting the mock objects behaviour
Mockito.when(customerRepo.saveAndFlush(cust)).thenReturn(cust);
Mockito.when(customerRepo.findByPhoneNo(
Mockito.eq("9876536751"))).thenReturn(null);

//Calling Service method to update customer
custService.updateCustomer("9876536751", "JubileeHills, Hyderabad");

//Verifying if the methods were called by customerservice
Mockito.verify(customerRepo).findByPhoneNo(Mockito.eq("9876536751"));
expectedException.expect(InfyTelException.class);
expectedException.expectMessage(ExceptionConstants.CUSTOMER_NOT_FOUND.toString());
try {
Mockito.verify(customerRepo).saveAndFlush(Mockito.any(Customer.class));
} catch (AssertionError e) {
}

}

Note: Similarly test methods for other functionalities have to be written