By kswaughs | Thursday, June 11, 2020

Spring WebFlux Mono Junit Test Example

This example shows how to write junit test for a method that returns Mono.

StepVerifier from io.projectreactor.reactor-test is used to test reactive components.

Below is the Service class that returns Mono.

BookService.java
package com.kswaughs.webflux;

import com.kswaughs.webflux.model.Book;

import reactor.core.publisher.Mono;

public class BookService {
    
    public Mono<Book> getBookById(int bookId) {
        
        if(bookId == 0) {
            return Mono.error(new Exception("Invalid BookId"));
        }
        
        if(bookId == 100) {
            
            return Mono.just(buildBook(bookId));
        }
        
        return Mono.empty();
    }
    
    private Book buildBook(int bookId) {
        
        Book book = new Book();
        
        book.setBookId(bookId);
        book.setAuthor("John Grisham");
        book.setTitle("A Painted House");

        return book;
    }
}


Below is the Junit test class to test Mono using StepVerifier

SpringWebFluxMonoExampleTest.java
package com.kswaughs.webflux;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

import reactor.test.StepVerifier;

public class SpringWebFluxMonoExampleTest {

    private BookService bookService = new BookService();

    @Test
    public void whenBookExists() {

        StepVerifier.create(bookService.getBookById(100))
            .assertNext(book -> {

                assertEquals(Integer.valueOf(100), book.getBookId());
                assertEquals("John Grisham", book.getAuthor());
                assertEquals("A Painted House", book.getTitle());
                
        }).verifyComplete();
    }
    
    @Test
    public void whenBookNotExists() {

        StepVerifier.create(bookService.getBookById(56))
            .verifyComplete();
    }
    
    @Test
    public void whenBookIdIsInvalid() {

        StepVerifier.create(bookService.getBookById(0))
        
          /** case 1: To validate only Exception className  **/
            //.expectError(Exception.class)
        
          /** case 2: To validate only exception message **/    
            //.expectErrorMessage("Invalid BookId")
        
          /** case 3: To Validate complete exception object **/    
            .expectErrorSatisfies(thr -> {
                assertTrue(thr instanceof Exception);
                assertEquals("Invalid BookId", thr.getMessage());
            })
            .verify();
    }
}

pom.xml
<dependency>
    <groupId>io.projectreactor</groupId>
    <artifactId>reactor-test</artifactId>
    <scope>test</scope>
</dependency>

Useful Links

Spring WebFlux Junit Test Example

Recommend this on


By kswaughs | Tuesday, June 9, 2020

Spring WebFlux Junit Test Example

This example shows how to write junit test for a method that returns Flux of Order objects.

StepVerifier from io.projectreactor.reactor-test is used to test reactive components.

Below is the Service class that returns Flux of three Order objects.

OrderService.java
package com.kswaughs.webflux;

import java.util.ArrayList;
import java.util.List;

import com.kswaughs.webflux.model.Order;

import reactor.core.publisher.Flux;

public class OrderService {
    
   public Flux<Order> getOrders() {
       
       List<Order> orders = new ArrayList<>();
       
       orders.add(buildOrder(345, 30, "DELIVERED"));
       orders.add(buildOrder(654, 50, "IN-TRANSIT"));
       orders.add(buildOrder(999, 12, "DELIVERED"));
       
       // return flux of orders..
       return Flux.fromIterable(orders);
   }

   private Order buildOrder(int orderId, double amount, String status) {
       
       Order order = new Order();
       order.setOrderId(orderId);
       order.setAmount(amount);
       order.setStatus(status);
       
       return order;
   }
}

Below is the Junit test class to test Flux of objects using StepVerifier

SpringWebFluxExampleTest.java
package com.kswaughs.webflux;

import static org.junit.Assert.assertEquals;

import org.junit.Test;

import com.kswaughs.webflux.model.Order;

import reactor.core.publisher.Flux;
import reactor.test.StepVerifier;

public class SpringWebFluxExampleTest {
    
    private OrderService orderService = new OrderService();

    @Test
    public void testGetOrders() {
        
        Flux<Order> orders = orderService.getOrders();
        
        StepVerifier.create(orders)
            // Above method is returning three orders.
            // we are asserting on first order only.
            .assertNext(order -> {
            
                assertEquals(Integer.valueOf(345), Integer.valueOf(order.getOrderId()));
                assertEquals(Double.valueOf(30), Double.valueOf(order.getAmount()));
                assertEquals("DELIVERED", order.getStatus());
            })
            // verifying count of next orders.
            .expectNextCount(2)
            .verifyComplete();
    }
}

pom.xml
<dependency>
    <groupId>io.projectreactor</groupId>
    <artifactId>reactor-test</artifactId>
    <scope>test</scope>
</dependency>

Useful Links

Spring WebFlux Mono Junit Test Example

Recommend this on


By kswaughs | Monday, June 1, 2020

Spring JdbcTemplate ResultSetExtractor Junit test example

This example shows how to write junit to test spring ResultSetExtractor functionality while mocking JdbcTemplate with Mockito.

This also increases code coverage of ResultSetExtractor code.

Below is the DAO class that returns Map of employees with ResultSetExtractor using Lambdas

Spring JdbcTemplate ResultSetExtractor Example with Lambdas
package com.kswaughs.dao;

import java.sql.ResultSet;
import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import com.kswaughs.beans.Employee;

@Repository
public class EmployeeDAO {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    public Map<Integer, Employee> getEmployeeMap() {

        return jdbcTemplate.query("SELECT ID, NAME, STATUS FROM EMPLOYEE",

            (ResultSet rs) -> {

                Map<Integer, Employee> employeeMap = new HashMap<>();

                while (rs.next()) {

                    Employee employee = new Employee();

                    employee.setId(rs.getInt("ID"));
                    employee.setName(rs.getString("NAME"));
                    employee.setStatus(rs.getBoolean("STATUS"));

                    employeeMap.put(employee.getId(), employee);
                }

                return employeeMap;
        });
    }
}

Below is the Junit test class to test ResultSetExtractor code by mocking JdbcTemplate to return two rows.

Spring JdbcTemplate ResultSetExtractor Junit test example
package com.kswaughs.dao;

import static org.mockito.Mockito.when;

import java.sql.ResultSet;
import java.util.Map;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentMatchers;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ResultSetExtractor;

import com.kswaughs.beans.Employee;

@RunWith(MockitoJUnitRunner.class)
public class EmployeeDAOTest {

    @Mock
    private JdbcTemplate jdbcTemplate;

    @InjectMocks
    private EmployeeDAO employeeDAO;

    @SuppressWarnings("unchecked")
    @Test
    public void testGetEmployeeMap() {

        Mockito.when(jdbcTemplate.query(
            ArgumentMatchers.anyString(), ArgumentMatchers.any(ResultSetExtractor.class)))
            .thenAnswer((invocation) -> {

                ResultSetExtractor<Map<Integer, Employee>> resultSetExtractor = 
                    (ResultSetExtractor<Map<Integer, Employee>>) invocation.getArgument(1);
                
                ResultSet rs = Mockito.mock(ResultSet.class);
                
                // two times it returns true and third time returns false.
                when(rs.next()).thenReturn(true, true, false);

                // Mock ResultSet to return two rows.
                Mockito.when(rs.getInt(ArgumentMatchers.eq("ID")))
                    .thenReturn(506, 400);
                Mockito.when(rs.getString(ArgumentMatchers.eq("NAME")))
                    .thenReturn("Jim Carrey", "John Travolta");
                Mockito.when(rs.getBoolean(ArgumentMatchers.eq("STATUS")))
                    .thenReturn(true, false);

                return resultSetExtractor.extractData(rs);
        });

        Map<Integer, Employee> employeeMap = employeeDAO.getEmployeeMap();
        
        // Assert First Row
        assertFirstUser(employeeMap.get(506));

        // Assert Second Row
        assertSecondUser(employeeMap.get(400));
    }

    public void assertFirstUser(Employee employee) {
        Assert.assertEquals(Integer.valueOf(506), employee.getId());
        Assert.assertEquals("Jim Carrey", employee.getName());
        Assert.assertTrue(employee.isStatus());
    }
    
    public void assertSecondUser(Employee employee) {
        Assert.assertEquals(Integer.valueOf(400), employee.getId());
        Assert.assertEquals("John Travolta", employee.getName());
        Assert.assertFalse(employee.isStatus());
    }
}

Recommend this on


By kswaughs | Thursday, May 28, 2020

Spring JdbcTemplate RowMapper Junit Test Example

This example shows how to write junit to test Spring RowMapper functionality while mocking JdbcTemplate with Mockito.

This also increases code coverage of RowMapper code.

Below is the DAO class that returns list of users with RowMapper using Lambdas.

Spring JdbcTemplate RowMapper Example with Lambdas
package com.kswaughs.dao;

import java.sql.ResultSet;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import com.kswaughs.beans.User;

@Repository
public class UserDAO {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    public List<User> getAllUsers() {

        return jdbcTemplate.query("SELECT ID, NAME, STATUS FROM USER", 
            
            (ResultSet rs, int rowNum) -> {

                User user = new User();

                user.setId(rs.getInt("ID"));
                user.setName(rs.getString("NAME"));
                user.setStatus(rs.getBoolean("STATUS"));

                return user;
            });
        }
    }

Below is the Junit test class to test RowMapper code by mocking JdbcTemplate to return two rows.

Spring JdbcTemplate RowMapper Junit test example
package com.kswaughs.dao;

import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentMatchers;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;

import com.kswaughs.beans.User;

@RunWith(MockitoJUnitRunner.class)
public class UserDAOTest {

    @Mock
    private JdbcTemplate jdbcTemplate;

    @InjectMocks
    private UserDAO userDAO;

    @SuppressWarnings("unchecked")
    @Test
    public void testGetAllUsers() {

        Mockito.when(jdbcTemplate.query(
            ArgumentMatchers.anyString(), ArgumentMatchers.any(RowMapper.class)))
            .thenAnswer((invocation) -> {

                RowMapper<User> rowMapper = (RowMapper<User>) invocation.getArgument(1);
                ResultSet rs = Mockito.mock(ResultSet.class);

                // Mock ResultSet to return two rows.
                Mockito.when(rs.getInt(ArgumentMatchers.eq("ID")))
                    .thenReturn(506, 400);
                Mockito.when(rs.getString(ArgumentMatchers.eq("NAME")))
                    .thenReturn("Jim Carrey", "John Travolta");
                Mockito.when(rs.getBoolean(ArgumentMatchers.eq("STATUS")))
                    .thenReturn(true, false);

                List<User> users = new ArrayList<>();
                users.add(rowMapper.mapRow(rs, 0));
                users.add(rowMapper.mapRow(rs, 1));

                return users;
        });

        List<User> users = userDAO.getAllUsers();
        
        // Assert First Row
        assertFirstUser(users.get(0));

        // Assert Second Row
        assertSecondUser(users.get(1));
    }

    public void assertFirstUser(User user) {
        Assert.assertEquals(Integer.valueOf(506), user.getId());
        Assert.assertEquals("Jim Carrey", user.getName());
        Assert.assertTrue(user.isStatus());
    }
    
    public void assertSecondUser(User user) {
        Assert.assertEquals(Integer.valueOf(400), user.getId());
        Assert.assertEquals("John Travolta", user.getName());
        Assert.assertFalse(user.isStatus());
    }
}

Recommend this on


By kswaughs | Tuesday, July 19, 2016

How to assert exception and error message

Normally while writing junits to validators and other methods that throws exceptions, we will use either

1. @Test(expected) annotation on test method to validate only Exception class Or

2. Use try catch in test method and in catch block, write assert statement on getMessage() of exception to validate error message.

In real time, we will have to assert on both Exception type and its error message. If we use try catch for each and every business condition, out test code looks untidy and makes unreadable.

Junit library provides a special component called ExpectedException to validate both exception type and its message with the help of @Rule annotation. Let us see the below example

Exception Class
package com.kswaughs;

public class UserException extends Exception {
    
    public UserException(String message) {
        super(message);
    }

}

Validator Class
package com.kswaughs;

public class UserValidator {
    
    public void validateUserID(String userID) throws UserException {
        
        if(userID == null) {
            throw new UserException("UserId is Null");
        }
        
        if(! userID.startsWith("USER")) {
            throw new UserException("UserId is Invalid");
        }
    }

}

Validator Test
package com.kswaughs;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

public class UserValidatorTest {
    
    @Rule
    public ExpectedException expectedEx = ExpectedException.none();
    
    @Test
    public void whenUserIDIsNull() throws Exception {
        
        expectedEx.expect(UserException.class);
        expectedEx.expectMessage("UserId is Null");
        
        UserValidator validator = new UserValidator();
        validator.validateUserID(null);
        
    }
    
    @Test
    public void whenUserIDIsInvalid() throws Exception {
        
        expectedEx.expect(UserException.class);
        expectedEx.expectMessage("UserId is Invalid");
        
        UserValidator validator = new UserValidator();
        validator.validateUserID("12345");
        
    }
}

Recommend this on


By kswaughs | Tuesday, June 7, 2016

How to mock object that implements multiple interfaces

When a java class implements multiple interfaces then it is little difficult to mock and set expectations with type of its interfaces. Mockito provides some useful method Mockito.withSettings().extraInterfaces to overcome this difficulty. Let us see the below example.

Interface User
package com.kswaughs;

public interface User {
    
    public String getUserName(String Id);

}

Interface Customer
package com.kswaughs;

public interface Customer {
    
    public String getCustomerName(String Id);

}

Sample Java class that implements multiple interfaces
package com.kswaughs;

public class UserImpl implements User, Customer {

    @Override
    public String getCustomerName(String Id) {
        
        return "MyCustomer";
    }

    @Override
    public String getUserName(String Id) {
        
        return "MyUser";
    }

}

Junit Test class to mock and test UserImpl class
package com.kswaughs;

import junit.framework.Assert;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Matchers;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
public class UserTest {
    
    private User mockWithTestData() {
        
        User user = PowerMockito.mock(UserImpl.class , 
             Mockito.withSettings().extraInterfaces(Customer.class));
                
        PowerMockito.when(
             user.getUserName(Matchers.eq("test"))).thenReturn("TestUser");
        
        Customer customer = (Customer) user;
        
        PowerMockito.when(
             customer.getCustomerName(Matchers.eq("test"))).thenReturn("TestCustomer");
        
        return user;
    }
    
        
    @Test
    public void testNames() throws Exception {
        
        // Test 1 : with test data
        
        UserImpl userImplMock = (UserImpl) mockWithTestData();
        
        String userName = userImplMock.getUserName("test");
        String customerName = userImplMock.getCustomerName("test");
        
        Assert.assertEquals("TestUser", userName);
        Assert.assertEquals("TestCustomer", customerName);
        
        logOutput("1 : With Mock Data", userName, customerName);
        
        // Test 2 : with implementation data
        UserImpl user = new UserImpl();
        
        userName = user.getUserName("12345");
        customerName = user.getCustomerName("12345");
        
        Assert.assertEquals("MyUser", userName);
        Assert.assertEquals("MyCustomer", customerName);
        
        logOutput("2 : With Real Data", userName, customerName);
        
    }
        

    private void logOutput(String testCase, String userName, String customerName) {
        
        System.out.println("***** Test "+testCase +" ***** :");
        System.out.println("userName :" +userName);
        System.out.println("customerName :" +customerName);
        System.out.println("\n");
    }


Console Logs
***** Test 1 : With Mock Data ***** :
userName :TestUser
customerName :TestCustomer


***** Test 2 : With Real Data ***** :
userName :MyUser
customerName :MyCustomer

Recommend this on


By kswaughs | Tuesday, September 15, 2015

How to Mock Spring RestTemplate using PowerMockito

Spring RestTemplate methods are defined using generics. Below is the method definition which is used to call rest service.

public <T>ResponseEntity<T> exchange(
        String url,
        HttpMethod method,
        HttpEntity<?> requestEntity,
        Class<T> responseType)
    throws RestClientException

Sample code to call Rest web service
public RestResponse callRestService(RestRequest request) {
   
     HttpHeaders headers = new HttpHeaders();
     headers.setAccept(Arrays.asList(new MediaType[] { MediaType.APPLICATION_JSON }));
     headers.setContentType(MediaType.APPLICATION_JSON);
 
     HttpEntity<RestRequest> entityReq = new HttpEntity<RestRequest>(
          request, headers);

     RestTemplate template = new RestTemplate();

     ResponseEntity<RestResponse> respEntity = template.
          exchange("RestSvcUrl", HttpMethod.POST, entityReq, RestResponse.class);
 
     return respEntity.getBody();
}

Junit Test method to mock RestTemplate
public void mockRestTemplate() throws Exception {
 
    // Mock RestTemplate 
    RestTemplate restTemplate = PowerMockito.mock(RestTemplate.class);
    PowerMockito.whenNew(RestTemplate.class).withNoArguments().
          thenReturn(restTemplate);
 
    // Create sample test response  
    RestResponse testResponse = new  RestResponse();
    // Build the response with required values
    /**  Call setters of testResponse   **/ 
    ResponseEntity<RestResponse> respEntity = new ResponseEntity<RestResponse>(
          testResponse, HttpStatus.ACCEPTED);
 
    // Set expectation on mock RestTemplate
    PowerMockito.when(restTemplate.exchange(
          Matchers.anyString(), 
          Matchers.any(HttpMethod.class),
          Matchers.<HttpEntity<RestRequest>> any(),
          Matchers.any(Class.class)))
      .thenReturn(respEntity);
}

You can set expectation without specifying the request class of the HttpEntity.

   PowerMockito.when(restTemplate.exchange(
         Matchers.anyString(), 
         Matchers.any(HttpMethod.class),
         Matchers.<HttpEntity<?>> any(),
         Matchers.any(Class.class)))
     .thenReturn(respEntity);

Recommend this on


By kswaughs | Sunday, August 23, 2015

Mock Java Objects with Mockito Framework

Mockito is a popular mock framework which can be used in conjunction with JUnit. Mockito allows you to create and configure mock objects.

Declaring a dependency to Mockito Using Maven

    <dependency>
      <groupId>org.mockito</groupId>
      <artifactId>mockito-all</artifactId>
      <version>1.8.5</version>
      <scope>test</scope>
    </dependency>

Using Mockito

Mockito supports the creation of mock objects with the static mock() method call. It also supports the creation of mock objects based on the @Mock annotation. If you use annotations, you must initialize this mock objects with a MockitoAnnotations.initMocks(this) method call or annotate your class with the @RunWith(MockitoJUnitRunner.class) annotation to use the Mockito test runner.

Different ways of creation of mock objects

Using Mockito.mock()
import org.junit.*;
import org.mockito.Mockito;

public class SampleTest {

     private UserService userSvc; // class to be tested

     UserDAO userDao; // dependant class to be mocked

     @Before
     public void setUp() {

          userDao = (UserDAO) Mockito.mock(UserDAO.class);

          userSvc = new UserService();
          userSvc.setUserDAO(userDao); // Stubbing the mock object
     }
}

Using annotations with initMocks
import org.junit.Before;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

public class SampleTest {

     private UserService userSvc; // class to be tested

     @Mock
     UserDAO  userDao;  

     @Before
     public void setUp() {
 
          MockitoAnnotations.initMocks(this);
          
          userSvc = new UserService();
          userSvc.setUserDAO(userDao); // Stubbing the mock object
     }
} 

Using annotations with MockitoJUnitRunner
import org.junit.Before;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class SampleTest {

     private UserService userSvc; // class to be tested

     @Mock
     UserDAO userDao;

     @Before
     public void setUp() {

          userSvc = new UserService();
          userSvc.setUserDAO(userDao); // Stubbing the mock object

     }

}

In the above samples, we have seen how to declare a mock object with mockito. Now we will see how to set the expectations on mock objects so that the mock object retuns the desired output when a method on the mock object gets executed. A complete junit test class with mockito framework looks as below

Basic structure of Junit with Mockito
import static org.junit.Assert.assertEquals;
import org.junit.*;

@RunWith(MockitoJUnitRunner.class)
public class SampleTest {

    private UserService userSvc;

    @Mock
    UserDAO  userDao; 

    @Before
    public void setUp() {
        userSvc = new UserService();
        userSvc.setUserDAO(userDao); // Stubbing the mock object
    }

    @Test 
    public void testWhenUserDetailsFound() throws Exception{  

       // Here set the expectations on mocked userDAO 
       // according to your test case scenario. 
            
       
       User user = userSvc.getUserById(“EMP341234”);
         
       assertEquals("EMP341234", user.getUserId() );
       assertEquals("JOHN", user.getUserName() );

     }  
}

Different ways of expectations supported by Mockito

Mockito.when() method is used to set expectations. Below is the import statement is required in your test class.

import  org.mockito.Mockito;

When method does not have any arguments
Class : Processor
Method : String getUserName();

Mockito.when(processor.getUserName()).thenReturn(“JOHN WOO”);   

When method has a String argument
Class : Processor
Method : String getUserName(String id);

//Case : Return the expected name for any string argument

Mockito.when(processor.getUserName(Matchers.anyString())).
      thenReturn(“JOHN WOO”);

//Case : Return the expected name for specific string argument

Mockito.when(processor.getUserName(Matchers.eq("EMP123"))).
      thenReturn(“JOHN WOO”); 

When method has user defined object as an argument
Class : Processor
Method : String getUserDetails(UserRequest req);

Mockito.when(processor.getUserName(Matchers.any (UserRequest.class))).
      thenReturn(“JOHN WOO”); 

Mock a method to throw some exception
Class : Processor
Method : String getUserDetails(UserRequest req) throws InvalidUserException

//Case : throw exception without constructing the exception object

Mockito.when(processor.getUserName(Matchers.any (UserRequest.class))).
      thenThrow(InvalidUserException.class);

//Case : throw exception with constructing the exception object

Mockito.when(processor.getUserName(Matchers.any(UserRequest.class))).
      thenThrow(new  InvalidUserException()); 

Partial Mocking

Partial mock means mock one method to return expected response and other methods to be called real ones. When you mock an object, you have to set expectations on all the methods, otherwise they will return null as their behaviour are not defined after a mock object is created. So if you want a partial mocking then use spy() method.

Mock a method with spy
Class : Processor
Method : String getUserDetails(UserRequest req) throws InvalidUserException

Processor  processor = Mockito.spy(new Processor());

// Set expectations as below like any other mocked object.

Mockito.when(processor.getUserName(Matchers.any(UserRequest.class))).
      thenThrow(new InvalidUserException());
 

Mockito limitations

With Mockito, we cannot mock the below types of classes.

1. static methods
2. final classes & methods
3. classes instantiated in a method

The solution is to use PowerMockito. 

Recommend this on


By kswaughs | Sunday, August 16, 2015

Junit tutorial

JUnit is an open source unit testing framework designed by Kent Beck, Erich Gamma for the purpose of writing and running test cases for java programs. That java program can be either a small program or a complex architecture applications like web services and web applications.

In case of web applications and web services, JUnit is used to test the application with out deploying in any server. This framework builds a relationship between development and testing process.

UNIT Testing is a software testing method by which individual units of source code are tested to determine whether they are fit for use and working as it should be. The primary goal of unit testing is to take the smallest piece of testable software in the application, isolate it from the remainder of the code, and validate its behavior. Individual unit might be a method of a class, group of classes.

WHERE THIS COMES INTO PICTURE

In the real world, to manufacture any product it should go through several phases of its life cycle. Similarly to develop a software for a user requirement, it should go through all the phases of below software development project life cycle.

  • Analysis 
  • Design 
  • Build 
  • Testing 
  • Production 
  • Maintenance

Most of the guys think that Unit testing is a part of ‘Testing’ phase as the name contains word testing. But this is wrong. Unit testing is a build activity and developers have to write and run the tests to make sure the code they written are working properly.

Benefits of writing JUNIT tests.

  • Ensures a quality and bug free code is delivered.
  • Issues and defects can be identified early in build phase.
  • Less or zero defects related to functionality will be raised in testing phase.
  • No need to deploy our code in any server to test the functionality.

STRUCTURE OF JUNIT CLASS

JUnit is also a java class written with some test methods to test the actual code. Usually the code that we want to test is a Java method which takes some input as method arguments and provides the output as a method return type. That method may return different kinds of response based on input values or some back-end data. So, we write different test methods to validate all the scenarios by providing the input accordingly.

Basic structure of the Junit class
import org.junit.*;
import static org.junit.Assert.*;
import java.util.*;
 
/**
 * @author Srinivas
 *
 */
public class SampleJunitTest {
 
    @BeforeClass
    public static void oneTimeSetUp() {
        // one-time initialization code   
     System.out.println("@BeforeClass - oneTimeSetUp : Runs before all test methods");
    }
 
    @AfterClass
    public static void oneTimeTearDown() {
        // one-time cleanup code
    System.out.println("@AfterClass - oneTimeTearDown : Runs after all test methods");
    }
 
    @Before
    public void setUp() {
        System.out.println("@Before - setUp : Runs before every test method");
    }
 
    @After
    public void tearDown() {
         System.out.println("@After - tearDown : Runs after every test method");
    }
 
    @Test
    public void testMyMethodUseCase1() {
         System.out.println("@Test - testMyMethodUseCase1 : Actual test method");
    }
 
    @Test
    public void testMyMethodUseCase2() {
        System.out.println("@Test - testMyMethodUseCase2 : Another test method");
    }
}
Result

@BeforeClass - oneTimeSetUp : Runs before all test methods
@Before - setUp : Runs before every test method 
@Test - testMyMethodUseCase1 : Actual test method
@After - tearDown : Runs after every test method
@Before - setUp : Runs before every test method 
@Test - testMyMethodUseCase2 : Another test method
@After - tearDown : Runs after every test method
@AfterClass - oneTimeTearDown : Runs after all test methods

How to define a test in JUnit ?

A JUnit test is a method contained in a class which is only used for testing. This is called a Test class. To write a test with the JUnit 4.x framework you annotate a method with the @org.junit.Test annotation. In this method you use an assert method, typically provided by the JUnit or another assert framework, to check the actual result of a method call is same as expected result. These method calls are typically called asserts or assert statements.

You should provide meaningful messages in assert statements so that it is easier for the developer to identify the problem. This helps in fixing the issue, especially if someone looks at the problem, who did not write the code under test or the test code.

JUnit naming conventions

There are several potential naming conventions for JUnit tests. In widespread use is to use the name of the class under test and to add the

  •   "Test" suffix to the test class
  •   “test” prefix to the test method

For the test method names it is frequently recommended to use the meaningful business use case, as for example "testWhenAccountIsInactive" or "testWhenUserNameisInvalid" as this gives a good hint what should happen if the test method is executed. As a general rule, a test name should explain what the test does so that it can be avoided to read the actual implementation.

JUnit test suites

If you have several test classes, you can combine them into a test suite. Running a test suite will execute all test classes in that suite in the specified order. The “Suite Test” means bundle a few unit test cases and run it together. In Junit, both @RunWith and @Suite annotations are used to run the suite test.

The below example means both unit test EmployeeTest and CustomerTest will run together after MyJunitTest is executed.

Sample Test Suite Configuration
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
 
@RunWith(Suite.class)
@Suite.SuiteClasses({
        EmployeeTest.class,
        CustomerTest.class
})
public class MyJunitTest {

}

Basic JUnit code constructs and annotations

JUnit 4.x uses annotations to mark methods as test methods and to configure them. The following table gives an overview of the most important annotations in JUnit.

JUNIT Annotations

@Test

@Test
public void method()

The @Test annotation identifies a method as a test method.

@Test (expected = Exception.class)

Fails if the method does not throw the named exception

@Test(timeout=100)

Fails if the method takes longer than 100 milliseconds.

@Before

@Before
public void method()

This method is executed before each test. It is used to prepare the test environment (e.g., read input data, initialize the class).

@After

@After
public void method()

This method is executed after each test. It is used to clean up the test environment (e.g., delete temporary data, restore defaults). It can also save memory by cleaning up expensive memory structures.

@BeforeClass

@BeforeClass
public static void method()

This method is executed once, before the start of all tests. It is used to perform time intensive activities, for example, to connect to a database. Methods marked with this annotation need to be defined as static to work with JUnit.

@AfterClass

@AfterClass
public static void method()

This method is executed once, after all tests have been finished. It is used to perform clean-up activities, for example, to disconnect from a database. Methods annotated with this annotation need to be defined as static to work with JUnit.

@Ignore

@Ignore("Why disabled")

Ignores the test method. This is useful when the underlying code has been changed and the test case has not yet been adapted. Or If the execution time of this test is too long to be included. It is best practice to provide the optional description, why the test is disabled.

In JUnit 4, you have to declare “@BeforeClass” and “@AfterClass” methods as static methods.

Assert statements

JUnit provides static methods in the Assert class to test for certain conditions. These assert statements typically start with assert and allow you to specify the error message, the expected and the actual result. An assertion method compares the actual value returned by a test to the expected value, and throws an AssertionException if the comparison test fails.

The following table gives an overview of these methods. Parameters in [] brackets are optional and of type String.

Assert Statements

fail(message)

Let the method fail. Might be used to check that a certain part of the code is not reached or to have a failing test before the test code is implemented. The message parameter is optional.

assertTrue([message,] boolean condition)

Checks that the boolean condition is true.

assertFalse([message,] boolean condition)

Checks that the boolean condition is false.

assertEquals([message,] expected, actual)

Verifies that two values are the same. For arrays the reference is checked not the content of the arrays.

assertEquals([message,] expected, actual, tolerance)

Test that float or double values match. The tolerance is the number of decimals which must be the same.

assertNull([message,]object)

Checks that the object is null.

assertNotNull([message,] object)

Checks that the object is not null.

assertSame([message,] expected, actual)

Checks that both variables refer to the same object.

assertNotSame([message,] expected, actual)

Checks that both variables refer to different objects.

Test Methods.

Basically In Java, a functional method either returns a response object or throw some exceptions based on the business use case. When we are writing a unit test means, in test method we call the java method by passing required input data and validate the output object.

In the below example, We are testing UserService class that has a method called ‘getUserById’ which will return User object for the requested userId, if userid not found it throws UserNotFoundException.

Case 1: Validate the exception thrown by method
import org.junit.*;

public class SampleTest {

 private UserService userSvc;

 @Before
 public void setUp() {
        userSvc = new UserService();
  }

@Test(expected = UserNotFoundException.class)  
 public void testWhenInvalidUserIdIsPassed() {  
     userSvc.getUserById(“NOEMP45678”);
  }  
}

In the below example, We are testing again the same method as above but this time we are validating the message of the exception.

Case 2: Validate the error message in the exception thrown by method
import static org.junit.Assert.assertEquals;
import org.junit.*;
 
public class SampleTest {

 private UserService userSvc;

 @Before
 public void setUp() {
        userSvc = new UserService();
  }

@Test 
 public void testWhenInvalidUserIdIsPassed() {  
    try {
         userSvc.getUserById(“NOEMP45678”);
         Assert.fail("Should throw exception"); 
    } catch(UserNotFoundException exp) {
       assertEquals("Invalid Employee ID Format",exp.getMessage() );
    }
 }  
}

In the below example, We are testing the same method and validating the values of response object returned by that method.

Case 3: Validate the response object returned by method
import static org.junit.Assert.assertEquals;
import org.junit.*;
 
public class SampleTest {

private UserService userSvc;

 @Before
 public void setUp() {
        userSvc = new UserService();
  }

@Test 
 public void testWhenUserDetailsFound() throws Exception{  
      User user = userSvc.getUserById(“EMP341234”);
         
       assertEquals("EMP341234", user.getUserId() );
       assertEquals("JOHN", user.getUserName() );

     }  
}
 

Test execution order

JUnit assumes that all test methods can be executed in an arbitrary order. Well-written test code should not assume any order, i.e., tests should not depend on other tests. As of JUnit 4.11 the default which may vary from run to run. It is to use a deterministic, but not predictable, order for the execution of the tests.

You can use an annotation to define that the test methods are sorted by method name, in lexicographic order. To activate this feature, annotate your test class with the @FixMethodOrder(MethodSorters.NAME_ASCENDING) annotation. You can also explicitly set the default by using the MethodSorters.DEFAULT parameter in this annotation. You can also use MethodSorters.JVM which uses the JVM defaults, which may vary from run to run.

This article described Junit tutorial about the concepts of Junit framework and covered with sample examples. This seems so simple. Isn't right ?. The above discussed components are enough to write junit test cases as long as your java classes are independently implemented with out depending on any other back-end or external systems.

What If classes are back end dependant. Can't we write Junit test cases ?

Yes. You can still write junit test cases but the problem is that your classes will try to connect to those systems and you will get unexpected errors. If you provide all the back-end set up details then it will become an integration testing but not an unit test. The purpose of unit testing itself is to test the functionality of our java classes individually without depending on availability of back-end systems. In such cases, you have to use mocking frameworks like JMock, EasyMock or Mockito to by pass the actual methods of dependant classes. There is nothing to worry which one should you use. All java based mocking frameworks can be easily integrated into Junit, the difference will be in using the mocking methods provided by them.

Recommend this on