JUnit Testing
Unit Testing:
Here Unit indicates a Part of a Project which can be a task/story.Once code is completed by Developer, then That part must be tested.
Unit Testing = testing one part of project developed by Programmer.
JUnit 5 : JUnit is a Unit Test framework. It is Opensource Java Library.
=> To test our code (class), we need to define one class that is called asTest Case (Test class).
To define one Test case we should use
a. JUnit 5 Annotations
b. JUnit 5 Assert API
=> Here, JUnit Runtime is provided with 3 components and one platform runtime.
i. JUnit Jupiter Engine (JUnit 5 API)
ii. JUnit Vintage Engine (JUnit 4 and 3 APIs)
iii. Integration (TestNg, Mock...etc)
=> For Our Test cases (Class + method) object creation and test-method calling done by JUnit Platform Runtime.
1. Open pom.xml , provide Java version and JUnit Dependencies
==Example Code#1============================
package in.nit.test;
import org.junit.jupiter.api.Test;
// Test case: A class that will test our code
public class TestEmployee {
//test methods
@Test
public void testSave() {
System.out.println("HELLO-SAVE");
}
@Test
public void testUpdate() {
System.out.println("HELLO-UPDATE");
}
@Test
public void testDelete() {
System.out.println("HELLO-DELETE");
}
}
======================================================
@TestMethodOrder : We can define multiple test methods inside Testcase.Those are executed in Random order by default.
We can specify our own order using @TestMethodOrder + OrderAnnotation Here we need to provide @Order(number).
---Example-------------
package in.nit.test;
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
// Test case: A class that will test our code
@TestMethodOrder(OrderAnnotation.class)
public class TestEmployee {
//test methods
@Test
@Order(1)
public void testSave() {
System.out.println("HELLO-SAVE");
}
@Test
@Order(2)
public void testUpdate() {
System.out.println("HELLO-UPDATE");
}
@Test
@Order(3)
public void testDelete() {
System.out.println("HELLO-DELETE");
}
}
*) We can use @TestMethodOrder(Alphanumeric.class) for provide test method order.First sort using 0-9 if same found then compare with A-Z sorting order.
-_Example#2_-
package in.nit.test;
import org.junit.jupiter.api.MethodOrderer.Alphanumeric;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
// Test case: A class that will test our code
@TestMethodOrder(Alphanumeric.class)
public class TestEmployee {
//test methods
@Test
public void testSave() {
System.out.println("HELLO-SAVE");
}
@Test
public void testUpdate() {
System.out.println("HELLO-UPDATE");
}
@Test
public void testDelete() {
System.out.println("HELLO-DELETE");
}
}
==============================================================
@BeforeEach : To execute any logic once per test method before starting test method.
@AfterEach : To execute any logic once per test method after finishing test method.
@BeforeAll : To execute any logic once per test case before starting.
@AfterAll : To execute any logic once per test case after finishing.
--Example#3----
package in.nit.test;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class TestEmployee {
@BeforeAll
public static void setupOnce() {
System.out.println("FROM ONETIME SETUP");
}
@BeforeEach
public void setup() {
//setup, init data
System.out.println("FROM SETUP");
}
@Test
public void testSave() {
System.out.println("HELLO-SAVE");
}
@Test
public void testUpdate() {
System.out.println("HELLO-UPDATE");
}
@AfterEach
public void clear() {
System.out.println("CLEAR DATA");
}
@AfterAll
public static void closeAll() {
System.out.println("FROM ONETIME AT END");
}
}
Output:
FROM ONETIME SETUP
FROM SETUP
HELLO-SAVE
CLEAR DATA
FROM SETUP
HELLO-UPDATE
CLEAR DATA
FROM ONETIME AT END
*) @DisplayName : This annotation is used to provide 'Readable text' inplace of actual method and class names at JUnit console.
--Ex#4--
package in.nit.test;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
@DisplayName("TESTING EMPLOYEE TASK")
public class TestEmployee {
@BeforeAll
public static void setupOnce() {
System.out.println("FROM ONETIME SETUP");
}
@BeforeEach
public void setup() {
//setup, init data
System.out.println("FROM SETUP");
}
@Test
@DisplayName("TESTING SAVE METHOD")
public void testSave() {
System.out.println("HELLO-SAVE");
}
@DisplayName("TESTING UPDATE METHOD")
@Test
public void testUpdate() {
System.out.println("HELLO-UPDATE");
}
@AfterEach
public void clear() {
System.out.println("CLEAR DATA");
}
@AfterAll
public static void closeAll() {
System.out.println("ONCE AT END");
}
}
*) @Disabled : This annotation is used to specify Ignore one Test-method while executing test-case (do not execute test method)
--Ex#5--
package in.nit.test;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
@DisplayName("TESTING EMPLOYEE TASK")
public class TestEmployee {
@Test
@DisplayName("TESTING SAVE METHOD")
public void testSave() {
System.out.println("HELLO-SAVE");
}
@DisplayName("TESTING UPDATE METHOD")
@Test
@Disabled
public void testUpdate() {
System.out.println("HELLO-UPDATE");
}
}
-----------------------------------------------------------------------
*) @RepeatedTest and TestInfo
=> To execute any test method multiple time (like batch processing) using @RepeatedTest annotation.
Ex: Export 1-10 Records
Export 11-20 Records
Export 21-30 Records
=> To know our Test case details like classname,method name, display name,tag name etc we can use one interface TestInfo.
--Ex#6---
package in.nit.test;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.TestInfo;
@DisplayName("TESTING EMPLOYEE TASK")
public class TestEmployee {
@RepeatedTest(value = 3,name="{displayName} - {currentRepetition}/{totalRepetitions}")
@DisplayName("MULTIPLE TEST")
public void testMultiple(TestInfo info) {
//System.out.println("HELLO:"+info.getTestClass().get().getName());
//System.out.println("HELLO:"+info.getTestMethod().get().getName());
System.out.println("HELLO:"+info.getDisplayName());
}
}
==========================================================================
@Tag : These are used to filter test methods for execution in different environments.
For Example, i want to test export example in production env at same
i want to test delete operation only in development environment
then use tag concept and maven-surefire-plugin in pom.xml
---EX#7---
package in.nit.test;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
public class TestEmployee {
@Test
@Tag("dev")
public void testA() {
System.out.println("HELLO-TEST-A");
}
@Test
@Tag("prod")
public void testB() {
System.out.println("HELLO-TEST-B");
}
@Test
@Tag("prod")
public void testC() {
System.out.println("HELLO-TEST-C");
}
@Test
@Tag("dev")
public void testD() {
System.out.println("HELLO-TEST-D");
}
}
pom.xml
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
int.nit
JUnit5App
1.0
1.8
1.8
org.junit.jupiter
junit-jupiter-engine
5.6.2
test
org.apache.maven.plugins
maven-surefire-plugin
3.0.0-M5
prod
dev
=> Right click on Project > Run as > maven test.
(or)
=> Right click on code > Run as > Run Configuration
> Click on configuration
Assert API :
It is used to validate Test, IS CURRENT TEST PASS/FAIL? Expected Value is compared with Actual Result.
=> JUnit 5 has provided class : Assertions (org.junit.jupiter.api) which contains all static method "assert methods".
=> assert methods are used to compare Expected values with Actual Result.If matching TEST PASS, else TEST FAIL.
=> Ex assert method : assertEquals(expected, actual)
This method is used to compared expected value with actual value
------------------------Code---------------------------
1. Create one Maven simple project
2. pom.xml
1.8
1.8
org.junit.jupiter
junit-jupiter-engine
5.6.2
test
3. Define one class under src/main/java which needs testing
package in.nit.service;
public class Message {
public String showMsg(String name) {
return "Welcome to: Mr/Mrs/Ms "+name;
}
}
4. TestCase under src/test/java
package in.nit.test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import in.nit.service.Message;
public class TestMessage {
// Declare variables
private Message m;
private String expected;
private String actual;
//provide init-data
@BeforeEach
public void setup() {
m = new Message();
expected = "Welcome to :SAM";
actual = "";
}
//Do Unit Test
@Test
public void testShowMsg() {
actual = m.showMsg("SAM");
assertEquals(expected, actual,"Data may not be matching!");
}
//clear heap data /clear memory.
@AfterEach
public void clean() {
m = null;
expected = actual = null;
}
}
------------------------------------------------------------------------------
*) assertNotNull() / assertNull()
assertNotNull(object):
This method is used to specify that given object is not a null value
it holds data some data, else TEST FAIL.
assertNull(object): it indicates given object is null, else TEST FAIL.
*) assertDoesNotThrow(Executable) :
This is used to specify that our method call is not throwing any exception, else if it throwing then TEST FAIL.
--Code---------------
1. Project code
package in.nit.util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DbConnection {
public Connection getCon() throws ClassNotFoundException, SQLException {
Connection con=null;
Class.forName("com.mysql.jdbc.Driver");
con=DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","root");
return con;
}
}
2. Unit Test code
package in.nit.test;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import java.sql.Connection;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import in.nit.util.DbConnection;
public class TestDbConnection {
private DbConnection dbc;
private Connection con;
@BeforeEach
public void initData() {
dbc=new DbConnection();
}
@Test
public void testGetCon() {
assertDoesNotThrow(()->{
con=dbc.getCon();
});
assertNotNull(con,"Connection is Not created, Please check!");
}
@AfterEach
public void clean() {
dbc = null;
con = null;
}
}
-----------------------------------------------------------
*) assertSame(ob1,ob2): This method is used to test that GIVEN TWO REFERENCES are POINTED TO ONE OBJECT?
If yes TEST PASS, else TEST FAIL.
Q) What is the diff b/w assertSame() and assertEquals()?
A) assertEquals () : compares two objects data
assertSame() : compares object references.
*) fail() : This is used for testing multiple conditions, if they are not met Manually FAIL TEST CASE.
--Example: Testing Singleton DB Connections---
1. pom.xml
1.8
1.8
org.junit.jupiter
junit-jupiter-engine
5.6.2
test
mysql
mysql-connector-java
5.1.47
2. Project code
package in.nit.util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DbConUtil {
private static Connection con;
static {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","root");
} catch (SQLException e) {
e.printStackTrace();
}
}
public static Connection getCon() {
return con;
}
}
3. test case
package in.nit.test;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.fail;
import java.sql.Connection;
import org.junit.jupiter.api.Test;
import in.nit.util.DbConUtil;
public class TestDbConUtil {
@Test
public void testGetCon() {
Connection con1=DbConUtil.getCon();
Connection con2=DbConUtil.getCon();
//assertNotNull(con1,"Connection not created..");
if(con1==null || con2==null ) {
//TEST CASE IS FAILED
fail("CONNECTIONS ARE NOT CRATED..");
}
assertSame(con1, con2,"May not be Same Connection!");
}
}
------------------------------------------------------------
*) assertArrayEquals() :use this method to compare data of two arrays (expected, actual)
Test case:
package in.nit.test;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import org.junit.jupiter.api.Test;
public class TestSample {
@Test
public void testNormal() {
int expected[] = {10,20,30};
int actual[] = {10,20};
assertArrayEquals(expected, actual,"Data may not be same in two arrays!");
}
}
*)assertTrue()/assertFalse()
These methods are used to test one boolean condition/expression/value.
assertTrue(): boolean value is expected as TRUE, else TEST FAIL.
assertFalse(): boolean value is expected as FALSE, else TEST FAIL.
--Example--
package in.nit.test;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
public class TestSample {
@Test
public void testNormal() {
boolean exist = false;
assertTrue(exist,"Data may not exist!");
}
}
*) assertThrows(): Expecting that our logic thorws one expcetion as : T (Type)
assertThrows(ExpectedExceptionType.class, ()-> {our logic});
-_Ex_-
package in.nit.test;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.junit.jupiter.api.Test;
public class TestSample {
@Test
public void testNormal() {
assertThrows(NullPointerException.class, ()->{
throw new ArrayIndexOutOfBoundsException();
});
}
}
-----------------------------
assertAll(Executable...) : This is used to group all asset test methods and execute once.If all are PASS then TEST IS PASS, If one FAIL then TEST IS FAIL.
package in.nit.test;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.fail;
import java.sql.Connection;
import org.junit.jupiter.api.Test;
import in.nit.util.DbConUtil;
public class TestSample {
@Test
public void testNormal() {
assertAll(
()->{
assertNotNull(DbConUtil.getCon());
},
()->{
Connection con1,con2;
con1=DbConUtil.getCon();
con2=DbConUtil.getCon();
assertSame(con1, con2);
},
()->{
Connection con1,con2;
con1=DbConUtil.getCon();
con2=DbConUtil.getCon();
if(con1==null && con2==null) {
fail();
}
}
);
}
}
No Comments Yet!!