JUnit 5
JUnit 5
JUnit 5
JUnit 5
2
Pre-requisite: Core Java + Eclipse IDE knowledge + (Advance java basics)
JUnit
Unit Testing: The test done by programmer on own piece of code is called unit
testing.
Peer Testing: The unit testing done on 1 programmer's code/ task by his
colleague programmer is called Peer testing.
Note: We can run each Test case class manually to generate Test report. But, if
want get test report of all the classes together then take the support Test suite
class.
4
Eclipse IDE gives built-in Support for JUnit (i.e. eclipse gives JUnit
libraries as built-in libraries)
5
JUnit-platform-engine: This engine is responsible to load test case classes, to
create object for them and to call test methods.
JUnit-platform-launcher: Helps different IDEs, Tools like maven and etc. to
search and get JUnit.
Annotations:
@Test
@DisplayName
@BeforeEach
@AfterEach
@BeforeAll
@AfterAll
@Tag
@ParameterizedTest
@ValueSource
@NullSource
@EmptySource
@NullAndEmptySource
@TestMethodOrder
@Order and etc.
6
Generally, The Testcase class name starts or ends with Test word and all test
methods generally begins with "test" word.
e.g.
BankService (main class)
p float calcSimplelntrest(-, -)
p float getBalance(-)
Note: In Test Case classes, for each business method/ service method we need
to write variety of test methods not quantity test method.
File --> maven project --> next --> select maven-archetype-quickstart ->
next -->
7
group Id: nit
artifact Id: RJnitTestProj1
package: com.nt.service --> next --> finish.
Step 4: Develop Testcase class with Test Methods in src/test/java folder having
package com.nt.test.
Step 5: Then right click on the test class – Run As – JUnit Test
• Develop the above directory Structure and package, class, XML file and
add the jar dependencies in pom.xml file then use the following code
with in their respective file.
pom.xml
<dependencies>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-
jupiter-api -->
<dependency>
<groupId>org.junit.jupiter</groupId>
8
<artifactId>junit-jupiter-api</artifactId>
<version>5.7.0</version>
<scope>test</scope>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.7.0</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-
jupiter-params -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>5.7.0</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-
jupiter-engine -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.7.0</version>
<scope>test</scope>
</dependency>
</dependencies>
BankLoanService.java
package com.nt.service;
public class BankLoanService {
public float calcSimpleIntrestAmount(float pAmount, float rate, float
time) {
System.out.println("BankLoanService.calcSimpleIntrestAmount()");
return pAmount*rate*time/100.0f;
}
}
TestBankLoanService.java
package com.nt.test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import com.nt.service.BankLoanService;
import com.nt.service.BankLoanService;
9
Right click on the Test class then Run As then click JUnit Test. After that go to
JUnit console to check the success and all.
10
@Test: To make the method of Testcase class as the Test method
assertEquals()/ assertNotEquals(): To check whether expected result is equal or
not with actual result and to generate test report.
assertThrows(): To check expected exception has come or not.
BankLoanService.java
public float calcSimpleIntrestAmount(float pAmount, float rate, float
time) {
System.out.println("BankLoanService.calcSimpleIntrestAmount()");
if (pAmount<=0||rate<=0||time<=0)
throw new IllegalArgumentException("Invalid inputs");
return pAmount*rate*time/100.0f;
}
TestBankLoanService.java
@Test
public void testcalcSimpleIntrestAmountWithInvalidInut() {
BankLoanService service = new BankLoanService();
assertThrows(ArithmeticException.class, ()->{
service.calcSimpleIntrestAmount(0, 0, 0);
});
}
You will get error if read the Failure Trace you can get the problem and
followed by solution according that you can solve the problem.
11
TestBankLoanService.java
@Test
public void testcalcSimpleIntrestAmountWithBigNumber() {
BankLoanService service = new BankLoanService();
float actual = service.calcSimpleIntrestAmount(10000000, 2,
12);
float expected = 2400000.0f;
assertEquals(expected, actual, "may results not matching");
}
@Test
public void testcalcSimpleIntrestAmountWithInvalidInut() {
BankLoanService service = new BankLoanService();
assertThrows(ArithmeticException.class, ()->{
service.calcSimpleIntrestAmount(0, 0, 0);
}, "may results not matching");
}
Assert that expected and actual are equal within the given non-negative delta.
Delta value is the different that is allowed in the results.
TestBankLoanService.java
@Test
public void testcalcSimpleIntrestAmountWithBigNumber() {
BankLoanService service = new BankLoanService();
float actual = service.calcSimpleIntrestAmount(10000000, 2,
12);
float expected = 2400000.12f;
assertEquals(expected, actual, 0.5, "may results not
matching");
}
TestBankLoanService.java
@Test
public void testcalcSimpleIntrestAmountWithTimer() {
BankLoanService service = new BankLoanService();
assertTimeout(Duration.ofMillis(20000), ()->{
service.calcSimpleIntrestAmount(100000, 2, 12);
});
}
@BeforeEach: To place common logic that should execute before each Test
method execution.
@AfterEach: To place common logic that should execute after the
each Test method execution.
TestBankLoanService.java
private BankLoanService service;
@BeforeEach
public void setUp() {
service = new BankLoanService();
}
@Test 13
public void testcalcSimpleIntrestAmountWithSmallNumber() {
System.out.println("TestBankLoanService.testcalcSimpleIntrestAmou
@Test
public void testcalcSimpleIntrestAmountWithSmallNumber() {
System.out.println("TestBankLoanService.testcalcSimpleIntrestAmou
ntWithSmallNumber()");
float actual = service.calcSimpleIntrestAmount(100000, 2, 12);
float expected = 24000.0f;
assertEquals(expected, actual, "may results not matching");
}
@Test
public void testcalcSimpleIntrestAmountWithBigNumber() {
System.out.println("TestBankLoanService.testcalcSimpleIntrestAmou
ntWithBigNumber()");
float actual = service.calcSimpleIntrestAmount(10000000, 2,
12);
float expected = 2400000.12f;
assertEquals(expected, actual, 0.5, "may results not
matching");
}
@AfterEach
public void clear() {
service = null;
}
@BeforeAll: To write common logic only for 1 time for all test methods.
@AfterAll: To place cleanup logic for all test methods.
These methods must be taken as static methods
TestBankLoanService.java
private static BankLoanService service;
@BeforeAll
public static void setUpOnce() {
service = new BankLoanService();
}
@AfterAll
public static void clearOnce() {
service=null;
}
14
JUnit Life cycle call back Annotation:
TestBankLoanService.java
@DisplayName("TestBankLoanService class")
public class TestBankLoanService {
@Test
@DisplayName("Testing with small numbers")
public void testcalcSimpleIntrestAmountWithSmallNumber() {
System.out.println("TestBankLoanService.testcalcSimpleIntrestAmou
ntWithSmallNumber()");
float actual = service.calcSimpleIntrestAmount(100000, 2, 12);
float expected = 24000.0f;
assertEquals(expected, actual, "may results not matching");
}
@Test 15
public void testcalcSimpleIntrestAmountWithBigNumber() {
System.out.println("TestBankLoanService.testcalcSimpleIntrestAmou
@Test
@Disabled
@DisplayName("Testing with timer")
public void testcalcSimpleIntrestAmountWithTimer() {
System.out.println("TestBankLoanService.testcalcSimpleIntrestAmou
ntWithTimer()");
assertTimeout(Duration.ofMillis(20000), ()->{
service.calcSimpleIntrestAmount(100000, 2, 12);
});
}
MethodOrderer (l):
It is having multiple inner classes implementing same MethodOrderer (l) they
are
a. MethodName
b. DisplayName (gives ambiguity with @DisplayName, so specify
MethodOrderer.DisplayName.class)
c. OrderAnnotation (best, we should add @Order(n) on top of test
methods while using this option. n-> priority number high value
indicates low priority and low value indicate high priority)
16
d. Random (default but gives ambiguity, so specify
MethodOrderer.Random.class)
e. AlphaNumeric (deprecated)
@Tag: Useful to mark test methods to execute only in certain environment like
"dev", "test", "uat", "prod" and etc. So, that we can write separate test
methods for "dev", "test" environment based light weight setup like using
MySQL, Tomcat server and etc. and similarly we can write separate test
methods for "uat", "prod" environment based heavy weight production ready
setup like using Oracle, WebLogic , Wildfly and etc.
TestBankLoanService.java
@Test
@DisplayName("Testing with small numbers")
@Tag("dev")
public void testcalcSimpleIntrestAmountWithSmallNumber() {
System.out.println("TestBankLoanService.testcalcSimpleIntrestAmou
ntWithSmallNumber()");
float actual = service.calcSimpleIntrestAmount(100000, 2, 12);
float expected = 24000.0f;
assertEquals(expected, actual, "may results not matching");
}
@Test
@DisplayName("Testing with Big numbers")
@Tag("uat")
public void testcalcSimpleIntrestAmountWithBigNumber() {
System.out.println("TestBankLoanService.testcalcSimpleIntrestAmou
ntWithBigNumber()");
float actual = service.calcSimpleIntrestAmount(10000000, 2,
12);
float expected = 2400000.12f;
17
assertEquals(expected, actual, 0.5, "may results not
matching");
}
float expected = 2400000.12f;
assertEquals(expected, actual, 0.5, "may results not
matching");
}
@Test
@DisplayName("Testing with invalid inputs")
@Tag("uat")
public void testcalcSimpleIntrestAmountWithInvalidInut() {
System.out.println("TestBankLoanService.testcalcSimpleIntrestAmou
ntWithInvalidInut()");
assertThrows(IllegalArgumentException.class, ()->{
service.calcSimpleIntrestAmount(0, 0, 0);
}, "may results not matching");
}
@Test
@Disabled
@DisplayName("Testing with timer")
@Tag("dev")
public void testcalcSimpleIntrestAmountWithTimer() {
System.out.println("TestBankLoanService.testcalcSimpleIntrestAmou
ntWithTimer()");
assertTimeout(Duration.ofMillis(20000), ()->{
service.calcSimpleIntrestAmount(100000, 2, 12);
});
}
• While running Test case class, we need to specify tags to include and
exclude
a. In Eclipse Environment
Right click Testcase class --> Run As --> Run Configurations -->
18
Include tags: uat
exclude tags: dev --> ok
Output:
19
b. In Maven Environment
Specify the tag names as shown below under surefire plugin.
pom.xml
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<goal>dev</goal>
<excludedGroups>uat</excludedGroups>
</configuration>
</plugin>
Note: We can pass TestInfo (I) type parameter in the test method to know
more the current test method and its executing environment like tag name,
display name, test class name, test method name and etc.
TestBankLoanService.java
@Test
@DisplayName("Testing with timer")
@Tag("dev")
public void testcalcSimpleIntrestAmountWithTimer(TestInfo info) {
System.out.println("TestBankLoanService.testcalcSimpleIntrestAmou
ntWithTimer()");
System.out.println(info.getClass()+" "+info.getTags()+"
"+info.getDisplayName()+" "+info.getTestMethod().get().getName()+"
"+info.getTestClass().get().getClass());
assertTimeout(Duration.ofMillis(20000), ()->{
service.calcSimpleIntrestAmount(100000, 2, 12);
});
}
20
@RepeatedTest: Allows to execute test method repeatedly for multiple times
having control on count and name. It is very useful batch processing/ updating
related tests.
CensusService.java
package com.nt.service;
public class CensusService {
TestCensusService.java
package com.nt.test;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.RepeatedTest;
import com.nt.service.CensusService;
21
@ParameterizedTest: To execute one test method for multiple times with
different inputs/ params we can we @ParameterizedTest we can supply inputs
by using @ValueSource and other annotations.
CensusService.java
public boolean isOdd(int no) {
if (no%2==0)
return false;
else
return true;
}
public String sayHello(String user) {
return "Hello: "+user;
}
TestCensusService.java
@ParameterizedTest
@ValueSource(ints = {10, 21, 34, 56, 11, 78})
public void testIsOdd(int n) {
System.out.println("TestCensusService.testIsOdd()");
CensusService service = new CensusService();
assertTrue(service.isOdd(n));
}
@ParameterizedTest
22
@ValueSource(strings = {"raja", "ram"})
public void testSayHello(String user) {
System.out.println("TestCensusService.testSayHello()");
CensusService service = new CensusService();
assertEquals("Hello: "+user, service.sayHello(user));
}
23
TestPrinter.java
package com.nt.test;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.fail;
import org.junit.jupiter.api.Test;
import com.nt.service.Printer;
public class TestPrinter {
@Test
public void testSingletone() {
Printer p1 = Printer.getInstance();
Printer p2 = Printer.getInstance();
/*assertNotNull(p1);
assertNotNull(p2);*/
if (p1==null||p2==null)
fail("p1, p2 references must not be null");
assertSame(p1, p2);
}
}
Note: If want to write failure message by writing manual checking then use
fail(-) method.
24