Junit - Testing Framework For Java: Types of Unit Testing
Junit - Testing Framework For Java: Types of Unit Testing
To perform unit testing, we need to create test cases. The unit test case is a code
which ensures that the program logic works as expected.
The org.junit package contains many interfaces and classes for junit testing such as
Assert, Test, Before, After etc.
1) Manual Testing
If you execute the test cases manually without any tool support, it is known as
manual testing. It is time consuming and less reliable.
2) Automated Testing
If you execute the test cases by tool support, it is known as automated testing. It is
fast and more reliable.
The Junit 4.x framework is annotation based, so let's see the annotations that can
be used while writing the test cases.
Let's write the logic to find the maximum number for an array.
package com.java.logic;
public class Calculation {
public static int findMax(int arr[]){
int max=0;
for(int i=1;i<arr.length;i++){
if(max<arr[i])
max=arr[i];
}
return max;
}
}
Here, we are using JUnit 4, so there is no need to inherit TestCase class. The main
testing code is written in the testFindMax() method. But we can also perform some
task before and after each test, as you can see in the given program.
package com.java.testcase;
import static org.junit.Assert.*;
import com.javatpoint.logic.*;
import org.junit.Test;
public class TestLogic {
@Test
public void testFindMax(){
assertEquals(4,Calculation.findMax(new int[]{1,3,4,2}));
assertEquals(-1,Calculation.findMax(new int[]{-12,-1,-3,-4,-2}));
}
}
To run this example, right click on TestLogic class -> Run As -> 1Junit Test.
Output:Assertion Error
As you can see, when we pass the negative values, it throws AssertionError because
second time findMax() method returns 0 instead of -1. It means our program logic is
incorrect.
Correct program logic
As you can see, program logic to find the maximum number for the given array is
not correct because it doesn't return -1 in case of negative values. The correct
program logic is given below:
package com.java.logic;
public class Calculation {
public static int findMax(int arr[]){
int max=arr[0];//arr[0] instead of 0
for(int i=1;i<arr.length;i++){
if(max<arr[i])
max=arr[i];
}
return max;
}
}
If you run the junit program again, you will see the following output.
Success
package com.java.logic;
public class Calculation {
//method that returns maximum number
public static int findMax(int arr[]){
int max=0;
for(int i=1;i<arr.length;i++){
if(max<arr[i])
max=arr[i];
}
return max;
}
//method that returns cube of the given number
public static int cube(int n){
return n*n*n;
}
//method that returns reverse words
public static String reverseWord(String str){
StringBuilder result=new StringBuilder();
StringTokenizer tokenizer=new StringTokenizer(str," ");
while(tokenizer.hasMoreTokens()){
StringBuilder sb=new StringBuilder();
sb.append(tokenizer.nextToken());
sb.reverse();
result.append(sb);
result.append(" ");
}
return result.toString();
}
}
package com.java.testcase;
import static org.junit.Assert.assertEquals;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import com.javatpoint.logic.Calculation;
public class TestCase2 {
@BeforeClass
public static void setUpBeforeClass() throws Exception {
System.out.println("before class");
}
@Before
public void setUp() throws Exception {
System.out.println("before");
}
@Test
public void testFindMax(){
System.out.println("test case find max");
assertEquals(4,Calculation.findMax(new int[]{1,3,4,2}));
assertEquals(-2,Calculation.findMax(new int[]{-12,-3,-4,-2}));
}
@Test
public void testCube(){
System.out.println("test case cube");
assertEquals(27,Calculation.cube(3));
}
@Test
public void testReverseWord(){
System.out.println("test case reverse word");
assertEquals("ym eman si nahk",Calculation.reverseWord("my name is khan");
}
@After
public void tearDown() throws Exception {
System.out.println("after");
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
System.out.println("after class");
}
}
Output:before class
before
test case find max
after
before
test case cube
after
before
test case reverse word
after
after class
Test suite is used to bundle a few unit test cases and run them together. In JUnit,
both @RunWith and @Suite annotations are used to run the suite tests.
Example having two test classes, TestJunit1 & TestJunit2, that run together using
Test Suite.
Create a Class
Create a java class to be tested, say, MessageUtil.java in C:\
>JUNIT_WORKSPACE.
/*
* This class prints the given message on console.
*/
//Constructor
//@param message to be printed
public MessageUtil(String message){
this.message = message;
}
@Test
public void testPrintMessage() {
System.out.println("Inside testPrintMessage()");
assertEquals(message, messageUtil.printMessage());
}
}
@Test
public void testSalutationMessage() {
System.out.println("Inside testSalutationMessage()");
message = "Hi!" + "Robert";
assertEquals(message,messageUtil.salutationMessage());
}
}
@RunWith(Suite.class)
@Suite.SuiteClasses({
TestJunit1.class,
TestJunit2.class
})
public class JunitTestSuite {
}
System.out.println(result.wasSuccessful());
}
}
Mockito Framework
What is Mocking?
Mocking is a process of developing the objects that act as the mock or clone of the
real objects. In other words, mocking is a testing technique where mock objects are
used instead of real objects for testing purposes. Mock objects provide a specific
(dummy) output for a particular (dummy) input passed to it.
The mocking technique is not only used in Java but also used in any object-oriented
programming language. There are many frameworks available in Java for mocking,
but Mockito is the most popular framework among them.
To mock objects, you need to understand the three key concepts of mocking, i.e.,
stub, fake, and mock. Some of the unit tests involve only stubs, whereas some
involve fake and mocks.
The brief description of the mocking concepts is given below:
1. Stub: Stub objects hold predefined data and provide it to answer the calls
during testing. They are referred to as a dummy object with a minimum
number of methods required for a test. It also provides methods to verify
other methods used to access the internal state of a stub, when necessary.
Stub object is generally used for state verification.
2. Fake: Fake are the objects that contain working implementations but are
different from the production one. Mostly it takes shortcuts and also contains
the simplified version of the production code.
What is Mockito?
Mockito is a Java-based mocking framework used for unit testing of Java application.
Mockito plays a crucial role in developing testable applications. Mockito was released
as an open-source testing framework under the MIT (Massachusetts Institute of
Technology) License. It internally uses the Java Reflection API to generate mock
objects for a specific interface. Mock objects are referred to as the dummy or proxy
objects used for actual implementations.
The main purpose of using the Mockito framework is to simplify the development of
a test by mocking external dependencies and use them in the test code. As a result,
it provides a simpler test code that is easier to read, understand, and modify. We
can also use Mockito with other testing frameworks like JUnit and TestNG.
The Mockito framework was developed by upgrading the syntax and functionalities
of
Benefits of Mockito
Below are given some benefits of the Mockito framework:
Methods of Mockito
The Mockito framework provides a variety of methods such as mock(), verify(),
when(), etc., used to test Java applications. Using these predefined methods makes
testing very easy.
1. ToDoService doService = mock(ToDoService.class);
1. when(mock.someCode ()).thenReturn(5);
Mockito framework keeps track of all the method calls with their parameters for
mocking objects. After mocking, we can verify that the defined conditions are met or
not by using the verify() method. This type of testing is sometimes known
as behavioral testing. It checks that a method is called with the right parameters
instead of checking the result of a method call.
The verify() method is also used to test the number of invocations. So we can test
the exact number of invocations by using the times method, at least once
method, and at most method for a mocked method.
There are two types of verify() methods available in the Mockito class, which are
given below:
o verify() method: It verifies certain behavior happened once.
Syntax: <T> verify(T mock)
There are two types of spy() methods available in the Mockito class:
o spy() method: It creates a spy of the real object. The spy method calls the
real methods unless they are stubbed. We should use the real spies carefully
and occasionally, for example, when dealing with the legacy code.
Syntax: <T> spy(T object)
o spy() method with Class: It creates a spy object based on class instead of
an object. The spy(T object) method is particularly useful for spying abstract
classes because they cannot be instantiated.
Syntax: <T> spy(Class<T> classToSpy)
1. List spyArrayList = spy(ArrayList.class);
Step 1: Add Maven dependencies required by the application. The dependencies are
always added in pom.xml file of the application. In this example you need to add
the two dependencies:
JUnit dependency
Mockito dependency
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13-rc-1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>2.0.1-beta</version>
<scope>test</scope>
</dependency>
ToDoService.java
import java.util.List;
public interface ToDoService {
public List<String> getTodos(String user);
}
ToDoBusiness.java
import java.util.ArrayList;
import java.util.List;
public class ToDoBusiness {
public ToDoService doService;
public ToDoBusiness(ToDoService doService) {
this.doService = doService;
}
public List<String> getTodosforHibernate(String user) {
List<String> hibernatelist = new ArrayList<String>();
List<String> Combinedlist = doService.getTodos(user);
for(String todo: Combinedlist) {
if(todo.contains("Hibernate")) {
hibernatelist.add(todo);
}
}
return hibernatelist;
}
}
ToDoBusinessMock.java
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import java.util.List;
import org.junit.Test;
public class ToDoBusinessMock {
@Test
public void testusing_Mocks() {
ToDoService doService = mock(ToDoService.class);
List<String> combinedlist = Arrays.asList(" Use Core Java ", " Use Sprin
g Core ", " Use w3eHibernate ", " Use Spring MVC ");
when(doService.getTodos("dummy")).thenReturn(combinedlist);
ToDoBusiness business = new ToDoBusiness(doService);
List<String> alltd = business.getTodosforHibernate("dummy");
System.out.println(alltd);
assertEquals(1, alltd.size());
} }
Step 1: Create a mock test class named TestList for testing the List class.
TestList.java
import static org.junit.Assert.*;
import static org.mockito.Mockito.when;
import java.util.List;
import org.junit.Test;
import org.mockito.Mock;
public class TestList {
@Test
public void testList_ReturnsSingle_value() {
List mocklist = mock(List.class);
when(mocklist.size()).thenReturn(1);
assertEquals(1, mocklist.size());
assertEquals(1, mocklist.size());
System.out.println( mocklist.size());
System.out.println(mocklist);
}
}
Step 1: Create a JUnit test case named TestList for testing the List class.
TestList.java
import static org.junit.Assert.*;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.mock;
import java.util.List;
import org.junit.Test;
public class TestList {
@Test
public void testList_Returns_MultipleValues() {
List mocklist = mock(List.class);
when(mocklist.size()).thenReturn(1).thenReturn(2).thenReturn(3);
assertEquals(1, mocklist.size());
assertEquals(2, mocklist.size());
assertEquals(3, mocklist.size());
System.out.println(mocklist.size());
System.out.println(mocklist);
}
}
Example of mocking List.get() method
In this example, we are going to mock a List.get() method. To use
the get() method, we need to pass a value (number) in it, as shown in the example.
TestList.java
import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.List;
import org.junit.Test;
public class TestList {
@Test
public void testList_get() {
List mocklist = mock(List.class);
when(mocklist.get(0)).thenReturn("Mockito");
assertEquals("Mockito", mocklist.get(0));
System.out.println(mocklist.get(0));
}
}
Example:
Context of Testing:
Valid inputs
Invalid inputs
Errors, exceptions, and events
Boundary conditions
Everything that might break
Benefits of TDD:
Much less debug time
Code proven to meet requirements
Tests become Safety Net
Near zero defects
Shorter development cycles
Example of TDD
Here in this example, we will define a class password. For this class, we will try
to satisfy following conditions.
First, we write the code that fulfills all the above requirements.
Output:
After making changes to class PassValidator () if we run the test then the output
will be PASSED