DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

How are you handling the data revolution? We want your take on what's real, what's hype, and what's next in the world of data engineering.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

SBOMs are essential to circumventing software supply chain attacks, and they provide visibility into various software components.

Related

  • Why Testing is a Long-Term Investment for Software Engineers
  • JUnit, 4, 5, Jupiter, Vintage
  • Readability in the Test: Exploring the JUnitParams
  • Creating Your Swiss Army Knife on Java Test Stack

Trending

  • Scrum Smarter, Not Louder: AI Prompts Every Developer Should Steal
  • Threat Modeling for Developers: Identifying Security Risks in Software Projects
  • Event Storming Workshops: A Closer Look at Different Approaches
  • Microservices for Machine Learning
  1. DZone
  2. Testing, Deployment, and Maintenance
  3. Testing, Tools, and Frameworks
  4. Writing Tests With JUnit 5 and CDI 2.0

Writing Tests With JUnit 5 and CDI 2.0

This post provides a guide to JUnit's most recent release and its new features, with sample code for the updated assertions and extensions.

By 
Otavio Santana user avatar
Otavio Santana
DZone Core CORE ·
Feb. 02, 18 · Tutorial
Likes (4)
Comment
Save
Tweet
Share
16.6K Views

Join the DZone community and get the full member experience.

Join For Free

JUnit is the most popular test framework in the Java world. In the newest release, version 5.0.3, it brings new features that will make Java developers' lives more comfortable. It has Java 8 as a minimum requirement that allows further support for Java 8. This article will cover a simple sample with JUnit integrated with CDI 2.0.

In this version, there is break compatibility, such as the package org.junit.jupiter.api instead of org.junit:

JUnit 4 Junit 5

Assert

Assertions

Assume

Assumptions

@Before

@BeforeEach

@After

@AfterEach

@BeforeClass

@BeforeAll

@AfterClass

@AfterAll

@Ignore

@Disable

@Category

@Tag

@RunWith, @Rule and @ClassRule

@ExtendeWith


To set up JUnit 5.0 in a Maven project:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.soujava</groupId>
    <artifactId>jnunit</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>JUnit 5 set dependency</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>5.0.3</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.19.1</version>
                <dependencies>
                    <dependency>
                        <groupId>org.junit.platform</groupId>
                        <artifactId>junit-platform-surefire-provider</artifactId>
                        <version>1.0.3</version>
                    </dependency>
                </dependencies>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>


With the dependency defined, your project is ready to use JUnit 5:

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
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("Hello world test")
public class HelloWorldTest {


    @BeforeAll
    public static void beforeAll() {
        System.out.println("Before all");
    }

    @AfterAll
    public static void afterAll() {
        System.out.println("After all");
    }

    @BeforeEach
    public void beforeEach() {
        System.out.println("Before each test");
    }

    @AfterEach
    public void afterEach() {
        System.out.println("Before after test");
    }


    @Test
    @DisplayName("should returns equals values")
    public void shouldEquals() {
        Assertions.assertEquals(5, 2 + 3);
    }

    @Test
    @DisplayName("should returns not equals values")
    public void shouldNotEquals() {
        Assertions.assertNotEquals("Brazil", "Argetina");
    }

    @Test
    @DisplayName("should be not null")
    public void shouldNotNull() {
        Assertions.assertNotNull("Brazil");
    }
}


Image title

In this version, there is Lambda support, such as Assertions.assertAll and Assertions.assertTimeout, which both expect an Executable interface, as an interface with one single method that is a functional interface:

public class JunitWitJava8Support {

    @Test
    @DisplayName("That breaks compatibility instead of @Test(expected = NullPointerException.class)")
    public void shouldReturnNPE() {
        Assertions.assertThrows(NullPointerException.class, () -> {
            throw new NullPointerException();
        });
    }

    @Test
    public void shouldCheckErrorMessage() {
        String errorMessage = "Error message";
        NullPointerException exception = Assertions.assertThrows(NullPointerException.class, () -> {
            throw new NullPointerException(errorMessage);
        });
        Assertions.assertEquals(errorMessage, exception.getMessage());
    }

    @Test
    public void shouldShouldExecute() {
        Assertions.assertAll(() -> {
            Assertions.assertTrue(Collections.emptyList().isEmpty());
        }, () -> {
            Assertions.assertNull(null);
        });
    }

    @Test
    public void shouldGetResult() {

        Process process = new Process();
        String result = Assertions.assertTimeout(Duration.ofMillis(2000), process::process);
        Assertions.assertEquals("Message result", result);

    }


    class Process {

        String process() throws Exception {
            Thread.sleep(1000);
            return "Message result";
        }
    }
}


Extensions

Follow the documentation about the extension in JUnit 5:

In contrast to the competing Runner, @Rule, and @ClassRule extension points in JUnit 4, the JUnit Jupiter extension model consists of a single, coherent concept: the Extension API. Note, however, that Extension itself is just a marker interface.

Using a Mockito extension, you can use it integrated with JUnit, as in JUnit 4:

@ExtendWith(MockitoExtension.class)
public class ExtenseionMockitoTest {

    @Mock
    private Team team;

    @BeforeEach
    public void beforeEach() {
        Mockito.when(team.getName()).thenReturn("Bahia");
    }

    @Test
    public void shouldEquals() {
        Assertions.assertEquals("Bahia", team.getName());
    }

    @Test
    public void shouldInjectByParam(@Mock Team team) {
        Assertions.assertNotNull(team);
    }

    interface Team {

        String getName();
    }
}


In this article, we're going to use your Extension, however, to CDI 2.0. Basically, this extension once has a field with @Inject it will inject using the SeContainer in CDI using the fields qualifiers.

public class CDIExtension implements TestInstancePostProcessor {


    private static final SeContainer CONTAINER = SeContainerInitializer.newInstance().initialize();
    private static final Predicate<Annotation> IS_QUALIFIER = a -> a.annotationType().isAnnotationPresent(Qualifier.class);

    @Override
    public void postProcessTestInstance(Object testInstance, ExtensionContext context) throws IllegalAccessException {

        for (Field field : getFields(testInstance.getClass())) {
            if (field.getAnnotation(Inject.class) != null) {
                Annotation[] qualifiers = Stream.of(field.getAnnotations())
                        .filter(IS_QUALIFIER)
                        .toArray(Annotation[]::new);
                Object injected = CONTAINER.select(field.getType(), qualifiers).get();
                field.setAccessible(true);
                field.set(testInstance, injected);
            }
        }
    }

    private List<Field> getFields(Class<?> clazzInstance) {
        List<Field> fields = new ArrayList<>();
        if (!clazzInstance.getSuperclass().equals(Object.class)) {
            fields.addAll(getFields(clazzInstance.getSuperclass()));
        } else {
            fields.addAll(asList(clazzInstance.getDeclaredFields()));
        }
        return fields;
    }

}


Testing the Recommendation System

In the previous article, we discussed a system recommendation using Neo4J and EE4J now it's time to test it. In the code, there is a connection to Neo4J. However, a dependency on an external database does not seem like a good strategy, so for tests, we can use a Neo4J embedded database. Furthermore, this step creates an implementation of GraphProducer with the embedded database, then overrides to the external database. CDI handles it using the Alternatives annotation with higher priority:

@ApplicationScoped
@Alternative
@Priority(Interceptor.Priority.APPLICATION+10)
public class EmbeddedSupplier implements GraphSupplier {

    private Graph graph = Neo4jGraph.open(new File("").getAbsolutePath() + "/target/jnosql-graph");

    @Override
    @Produces
    public Graph get() {
        return graph;
    }
}


Concluding the embedded database, the next step is to create tests integrated with CDI:

@ExtendWith(CDIExtension.class)
public class CityRepositoryTest {

    @Inject
    @Database(DatabaseType.GRAPH)
    private CityRepository repository;

    @Test
    public void shouldFindById() {
        Name name =  Name.of("New York");
        City city = new City(name.get());

        repository.save(city);
        assertTrue(repository.findByName(name.get()).isPresent());
    }

    @Test
    public void shouldDeleteById() {
        Name name =  Name.of("New York");

        City city = new City(name.get());

        repository.save(city);
        assertTrue(repository.findByName(name.get()).isPresent());
        repository.deleteByName(name.get());
        assertFalse(repository.findByName(name.get()).isPresent());
    }

}


@ExtendWith(CDIExtension.class)
class BuddyServiceTest {

    @Inject
    private BuddyService service;

    @Inject
    private BuddyLoader loader;


    @BeforeEach
    public void setUp() {
        loader.loadVertex();
        loader.loadEdges();
    }

    @AfterEach
    public void after() {
        loader.clean();
    }


    @Test
    public void shouldFindByTechnology() {

        List<Buddy> javaDevelopers = service.findByTechnology(JAVA.getName());


        assertAll(() -> {
            assertFalse(javaDevelopers.isEmpty());
        }, () -> {
            assertEquals(2, javaDevelopers.size());
        }, () -> {
            Predicate<String> isJoao = "joao"::equalsIgnoreCase;
            Predicate<String> isJose = "jose"::equalsIgnoreCase;
            assertTrue(javaDevelopers.stream().map(Buddy::getDisplayName).allMatch(isJoao.or(isJose)));
        });
    }

}


References:

  • JUnit 5 extension

  • Sample code

  • CDI Spec

CDI JUnit Testing

Opinions expressed by DZone contributors are their own.

Related

  • Why Testing is a Long-Term Investment for Software Engineers
  • JUnit, 4, 5, Jupiter, Vintage
  • Readability in the Test: Exploring the JUnitParams
  • Creating Your Swiss Army Knife on Java Test Stack

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • [email protected]

Let's be friends: