Effective & Readable Unit Testing With Junit5
--
Last week I had to do Tech talk in Arimac & I though to share the content in written medium.
These are the new features I am going to discuss here.
- Display Names
- Group Assertions
- Conditional tests
- Parameterized Test(Update)
- Dynamic tests
- Nested tests
Here we are going to discuss some of the features are how to write effective Tests in Junit & other aspect we are going to talk is readability.
Setup
For Setup Junit5 in your java project You need java 1.8 & upwards
For My Setup I have created Sample Project. First We have to Add junit-jupiter-engine as dependency.
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.7.1</version>
<scope>test</scope>
</dependency>
Display Names
Display Names Helps to More readability In test cases while in run Time.
Used Annotation
@DisplayName
Example:
@Test
@DisplayName("Check Assertion Display Name")
void testSimpleAssertion() {
assertEquals(1, 1);
}
View
Group Assertions
The main advantage of Group Assertions is which helps to run multiple check & one time & It is not blocking if one error occurs.
Let’s See How We did in junit4 First.
@Test
@DisplayName("Junit 4 Way To Run Multiple Tests")
void testOldList() {
final BMICalculatorService bmiCalculatorService = new BMICalculatorService();
float bmi1 = bmiCalculatorService.calculateBMI(55, 161);
float bmi2 = bmiCalculatorService.calculateBMI(75, 161);
float bmi3 = bmiCalculatorService.calculateBMI(65, 135);
assertEquals(UserCategory.NORMAL, bmiCalculatorService.getUserCategory(bmi1));
assertEquals(UserCategory.OVER_WEIGHT, bmiCalculatorService.getUserCategory(bmi2));
assertEquals(UserCategory.OBESE, bmiCalculatorService.getUserCategory(bmi3));
}
The Problem here is if the second assertion failed, It will not be continue to check 3rd case.
Then We doing the same Thing in Junit5
@Test
@DisplayName("BMI Calculator")
void testMBICalculator() {
final BMICalculatorService bmiCalculatorService = new BMICalculatorService();
final float bmi1 = bmiCalculatorService.calculateBMI(55, 161);
float bmi2 = bmiCalculatorService.calculateBMI(75, 161);
Assertions.assertAll(() -> assertEquals(UserCategory.NORMAL, bmiCalculatorService.getUserCategory(bmi1)),
() -> assertEquals(UserCategory.NORMAL, bmiCalculatorService.getUserCategory(bmi2)),
() -> assertEquals(UserCategory.OVER_WEIGHT, bmiCalculatorService.getUserCategory(bmi2)));
}
This is the result when Failed second assertion.It got executed 3rd Times if assertions failed in middle.
Conditional Tests
When We write unit tests, There are some logic's we have to run based on condition . So Rather than check condition in program level We can do it by junit itself.
if the condition fails it will not execute the Test Case.
Parameterized Test
Parameterized Tests came up with junit 4, But In junit 5 there are lot of improvements when writing test cases. @ParameterizedTest is Sub Test of @Test annotation So no need to put both annotations.
These above two Test cases explain how we can use multiple parameters to check the assertions. The Biggest Advantage is Those Parameter values to object types. Read the supported Argument conversions Types
Dynamic Tests
This is the best feature I though which will provided by junit5. The reason is dynamically We can Create Test Cases which helps to do the Test in streams.
Here When stream list of Employee It will create Dynamic Test & gives the results. We have to make sure that test results need to return Stream, Collection, Iterable, Iterator of DynamicTest.
Nested tests
Netsted Test helps to write Unit Tests more readable way. If our class contains large number of test cases , Then We can organize Test using Nested Tests.
As Example :
@DisplayName("Nested Test Example")
class NetstedExampleTest {
@Test
@DisplayName("Test1")
void testDemo() {
assertEquals(1, 1);
}
@Test
@DisplayName("Test2")
void testLogic2() {
assertEquals(1, 1);
}
@Nested
@DisplayName("Inner Class")
class InnerLogicTest {
@Test
@DisplayName("Layer1")
void testLogic2() {
assertEquals(1, 1);
}
@Nested
@DisplayName("Layer One Class")
class LayerOneTest {
@Test
@DisplayName("Layer2")
void testLogic2() {
assertEquals(1, 1);
}
}
}
}
And Like this way It is easy to read.
And that is all. These Code Samples available in here