Changes

Jump to navigation Jump to search
8,641 bytes removed ,  13:40, 23 June 2022
m
no edit summary
Line 113: Line 113:  
==Unit tests==
 
==Unit tests==
   −
===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>
      
==Example: Spring Boot with Data JPA and in memory database H2==
 
==Example: Spring Boot with Data JPA and in memory database H2==

Navigation menu