8,641 bytes added
, 13:40, 23 June 2022
===Add Maven dependencies for JUnit===
<syntaxhighlight lang="xml">
....
<dependencies>
....
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.8.2</version>
<scope>test</scope>
</dependency>
....
</dependencies>
....
</syntaxhighlight>
===Package structure to create tests===
[[File:Pstructjstest.png|thumb|alt=|none]]
The convention is tu follow the structure shown on the image.
===Test example===
<syntaxhighlight lang="java">
package com.luv2code.junitdemo;
import org.junit.jupiter.api.Test;
// import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.DisplayNameGeneration;
import org.junit.jupiter.api.DisplayNameGenerator;
import static org.junit.jupiter.api.Assertions.*;
// https://leeturner.me/posts/building-a-camel-case-junit5-displaynamegenerator/
// @DisplayNameGeneration(DisplayNameGenerator.Simple.class)
// @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
@DisplayNameGeneration(DisplayNameGenerator.IndicativeSentences.class)
class DemoUtilsTest {
DemoUtils demoUtils;
@BeforeAll
static void setUpClass() {
System.out.println("Cleanup before all tests")
}
@BeforeEach
void setUp{
demoUtils = new DemoUtils();
int expected = 6;
}
@Test
// @DisplayName("Null and Not Null")
void testEqualsAndNotEquals() {
// Execute
int actual = demoUtils.add(2, 4);
// Assert
assertEquals(expected, actual, "2 + 4 must be 6");
}
@Test
void testNullAndNotNull(){
String str1 = null;
String str2 = "luv2code";
assertNull(demoUtils.checkNull(str1), "Object should be null");
assertNull(demoUtils.checkNull(str2), "Object should not be null");
}
@AfterEach
void tearDownAfterEach(){
System.out.println("Cleanup After each test");
}
@AfterAll
static void cleanUpClass(){
System.out.println("Cleanup After all tests");
}
}
</syntaxhighlight>
====Custom displayName generator for camelCase with numbers====
<syntaxhighlight lang="java">
static class ReplaceCamelCaseEmojis extends ReplaceCamelCase {
public ReplaceCamelCaseEmojis() {
}
public String generateDisplayNameForClass(Class<?> testClass) {
return this.replaceWithEmojis(super.generateDisplayNameForClass(testClass));
}
public String generateDisplayNameForNestedClass(Class<?> nestedClass) {
return this.replaceWithEmojis(super.generateDisplayNameForNestedClass(nestedClass));
}
public String generateDisplayNameForMethod(Class<?> testClass, Method testMethod) {
return this.replaceWithEmojis(super.generateDisplayNameForMethod(testClass, testMethod));
}
private String replaceWithEmojis(String name) {
name = name.replaceAll("Camel|camel", "\uD83D\uDC2B");
name = name.replaceAll("Case|case", "\uD83D\uDCBC");
name = name.replaceAll("Display|display", "\uD83D\uDCBB");
name = name.replaceAll("Divisible|divisible", "\u2797");
name = name.replaceAll("Year|year", "\uD83D\uDCC5");
name = name.replaceAll("100", "\uD83D\uDCAF");
return name;
}
}
</syntaxhighlight>
===Run unit test===
====All tests====
<syntaxhighlight lang="bash">
mvn test
</syntaxhighlight>
====Single test====
<syntaxhighlight lang="bash">
mvn -Dtest=TestMessageBuilder test
</syntaxhighlight>
====Single test method from one test class====
<syntaxhighlight lang="bash">
mvn -Dtest=TestMessageBuilder#testHelloWorld test
</syntaxhighlight>
===JUnit Assertions===
<br /><syntaxhighlight lang="java">
import static org.junit.jupiter.api.Assertions.*;
</syntaxhighlight>org.junit.jupiter.api.Assertions contains JUnit Assertions
assertEquals(expected, actual, optional_message)
assertNotEquals(unexpected, actual, optional_message)
assertNull()
assertNotNull()
assertSame(object1, object1, message)
assertNotSame(object1, object1, message)
assertTrue(boolvariable, message)
assertFalse(boolvariable, message)
assertArraysEqual(array1, array2, message)
assertIterableEquals(iterable1, iterable2 message)
assertLinesMatch??
assertThrows(Exception.class, ()-> {functionCallThatThrowsError(params);})
assertDoesNotThrows( ()-> {functionCallThatDoesNotThrowsError(params);})
assertTimeoutPreemptively(Duration.ofSeconds(3), () -> { demoUtils.checkTimeout(); }, "Method should execute in 3 seconds");
=== Run tests in order ===
By default the order of the tests is deterministic but not obious, you can force the order<syntaxhighlight lang="java">
// MethodOrderer.DisplayName, MethodOrderer..MethodName, MethodOrderer.Random, MethodOrderer.OrderAnnotation
@TestMethodOrder(MethodOrderer.DisplayName.class)
class DemoUtilsTest {
...
@DisplayName("Equals and not equals")
void testEqualsAndNotEquals()...
// ----------------------------------------------
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class DemoUtilsTest {
...
@DisplayName("Equals and not equals")
@Order(1)
void testEqualsAndNotEquals()...
</syntaxhighlight>
=== Configure maven to run tests ===
pom.xml<syntaxhighlight lang="xml">
<!-- Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Java -->
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<scope>test</scope>
</dependency>
</syntaxhighlight>
=== Code coverage ===
IntelliJ has built-in support for code coverage Maven can too, requires plugin like maven-surefire-report-plugin<syntaxhighlight lang="xml">
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-report-plugin</artifactId>
<version>3.0.0-M5</version>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>report</goal>
<goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</syntaxhighlight>mvn clean test
mvn site -DgenerateReports=false
<br /><syntaxhighlight lang="xml">
// at the surefire plugin
....
<configuration>
<testFailureIgnore>true</testFailureIgnore>
<statelessTestsetReporter implementation="org.apache.maven.plugin.surefire.extensions.junit5.JUnit5Xml30StatelessReporter">
<usePhrasedTestCaseMethodName>true</usePhrasedTestCaseMethodname>
</statelessTestsetReporter>
</configuration>
</plugin>
.....
</syntaxhighlight>
=== JaCoCo (Java Code Coverage) ===
<syntaxhighlight lang="xml">
...
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.7</version>
<executions>
<execution>
<id>jacoco-prepare</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>jacoco-report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
....
</syntaxhighlight>
=== Disable tests ===
<syntaxhighlight lang="java">
class ConditionalTest {
@Test
@Disabled("Dont run this test until ticket @34 is solved")
void basicTest() {}
@Test
@EnabledOnOs(OS.WINDOWS, OS.MAC, OS.LINUX)
void testForAllSystems() {}
@Test
@EnabledOnJre(JRE.JAVA_17)
void testOnJavaVersion() {}
@Test
@EnabledOnJreRange(min=JRE.JAVA_13, max=JRE.JAVA_18) // If only min provided works until latest java
void testOnJavaVersionRange() {}
@Test
@EnabledIfSystemProperty(named="SOMEPROPERTYNAME", matches="SOMEVALUE")
void testOnJavaVersion() {}
@Test
@EnabledIfEnvironmentVariable(named="SOMEPROPERTYNAME", matches="SOMEVALUE")
void testOnJavaVersion() {}
}
</syntaxhighlight>
=== Parameterized Tests ===
<syntaxhighlight lang="java">
// @parameterizedTest
@parameterizedTest(name="value={0}, expected={1}")
/* @CsvSource({
"1,1",
"2,2",
"3,Fizz",
"4,4",
"5,Buzz"
})*/
@CsvFileSource(resources="/small-test-data.csv") // src/test/resources/small-test-data.csv
void testCsvData(int value, String expected){
assertEquals(expected, FizzBuzz.compute(value));
}
</syntaxhighlight>