Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

4.x: Improved Helidon MP testing #9695

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

romain-grecourt
Copy link
Contributor

@romain-grecourt romain-grecourt commented Jan 25, 2025

Helidon MicroProfile Testing Improvements

Description

Test Instance Creation

The test instances are now created by CDI exclusively for both JUnit and TestNG.

This normalizes the use of CDI across both test frameworks.

Notable changes:

  • In the JUnit support, the restriction of using injection with resetPerTest = true has been removed.

The following code now works:

@ApplicationScoped
class MyBean {
}

@AddBean(MyBean.class)
@HelidonTest(resetPerTest = true)
class MyTest {

    @Inject
    MyBean myBean;
}
  • In the TestNG support, constructor injection can now be used

The following code now works:

@ApplicationScoped
class MyBean {
}

@AddBean(MyBean.class)
class MyTest {

    final MyBean myBean;

    @Inject
    MyTest(MyBean myBean) {
        this.myBean = myBean;
    }
}

JUnit Instance Lifecycle

Support for JUnit's lifecycle has been implemented.

I.e.

  • @TestInstance(TestInstance.Lifecycle.PER_CLASS) (default)
  • @TestInstance(TestInstance.Lifecycle.PER_METHOD)

The default is PER_CLASS and is set via @HelidonTest in order to retain compatibility.

Notable changes:

  • Existing restrictions of using @TestInstance have been removed.

The following code now works:

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@HelidonTest
class MyTest {

    @Test
    @Order(1)
    void firstTest() {
        // ...
    }

    @Test
    @Order(2)
    void secondTest() {
        // ...
    }
}

Improved Meta Annotation Support

The support for meta annotation has been improved. It is now possible to compose using all the MicroProfile Testing annotations.

E.g.

@HelidonTest
@DisableDiscovery
@AddJaxRs
@interface SuperTest {
}

@AddBean(FooResource.class)
@SuperTest
class FooTest {
    @Test
    void testFoo() {
        // ...
    }
}

Default AddBean Scope

Updated the @AddBean annotation to use an "undefined" default scope value.

This allows to use the scope defined on the bean class, unless the scope attribute is explicitly set.

@Path("/foo")
@RequestScoped
class MyResource {
}

@AddBean(MyResource.class)
@AddJaxRs
class MyTest {
    // MyResource is added with scope=RequestScoped
}

Implicit CDI Container Reset

Individual test methods can now request a dedicated CDI container without using @HelidonTest(resetPerTest = true).

@ApplicationScoped
class MyBean {
}

@HelidonTest
class MyTest {

    @Test
    void testFirst() {
        // uses the "class" CDI container
    }

    @Test
    @AddBean(MyBean.class)
    void testSecond() {
        // implicitly uses a dedicated CDI container
    }
}

Using the following annotations on methods creates a dedicated CDI container:

  • AddBean
  • AddExtension
  • DisableDiscovery
  • AddJaxRs
  • AddConfig
  • AddConfigBlock
  • Configuration

By default the methods that share the "class" container are grouped in order to prevent unnecessary restarts.

When using JUnit, a default method orderer is used to implement the grouping: HelidonImplicitResetOrderer.

Note that if a test class defines an orderer, the grouping must be done manually in order to prevent unnessary restarts.

When using TestNG, the methods are grouped and then sorted by priority.
I.e. The priority takes precedence.

Lazy CDI container Startup

The test class is now proxied (using ByteBuddy) in order to start the CDI container just in time.

This makes the extension order insignificant and thus improves the user experience with TestContainers.

In the example below, the Docker container is started before the CDI container:

@HelidonTest
@TestContainers
class MyTest {

    @Container
    static final MySQLContainer<?> CONTAINER = new MySQLContainer<>();
}

Automatic CDI Initializer Configuration

When using @Configuration(useExisting = true) the requirement to specify the CDI initializer configuration has been removed:

mp.initializer.allow=true
mp.initializer.no-warn=true

API changes

A new module: io.helidon.microprofile.testing has been created to share the API and implementation between the JUnit and TestNG integrations.

The following annotations are added:

io.helidon.microprofile.testing.AddBean
io.helidon.microprofile.testing.AddBeans
io.helidon.microprofile.testing.AddConfig
io.helidon.microprofile.testing.AddConfigs
io.helidon.microprofile.testing.AddConfigBlock
io.helidon.microprofile.testing.AddExtension
io.helidon.microprofile.testing.AddExtensions
io.helidon.microprofile.testing.AddJaxRs
io.helidon.microprofile.testing.AfterStop
io.helidon.microprofile.testing.Configuration
io.helidon.microprofile.testing.DisableDiscovery
io.helidon.microprofile.testing.Socket

The following annotations are deprecated:

io.helidon.microprofile.testing.junit5.AddBean
io.helidon.microprofile.testing.junit5.AddBeans
io.helidon.microprofile.testing.junit5.AddConfig
io.helidon.microprofile.testing.junit5.AddConfigs
io.helidon.microprofile.testing.junit5.AddConfigBlock
io.helidon.microprofile.testing.junit5.AddExtension
io.helidon.microprofile.testing.junit5.AddExtensions
io.helidon.microprofile.testing.junit5.AddJaxRs
io.helidon.microprofile.testing.junit5.AfterStop
io.helidon.microprofile.testing.junit5.Configuratio
io.helidon.microprofile.testing.junit5.DisableDiscovery
io.helidon.microprofile.testing.junit5.Socket
io.helidon.microprofile.testing.testng.AddBean
io.helidon.microprofile.testing.testng.AddBeans
io.helidon.microprofile.testing.testng.AddConfig
io.helidon.microprofile.testing.testng.AddConfigs
io.helidon.microprofile.testing.testng.AddConfigBlock
io.helidon.microprofile.testing.testng.AddExtension
io.helidon.microprofile.testing.testng.AddExtensions
io.helidon.microprofile.testing.testng.AddJaxRs
io.helidon.microprofile.testing.testng.Configuration
io.helidon.microprofile.testing.testng.DisableDiscovery
io.helidon.microprofile.testing.testng.Socket

This addresses the API duplication that currently exists between the JUnit and TestNG integrations.

The deprecated APIs will remain in 4.x and will be removed in 5.0.

The JUnit extension class is now public and usable with @ExtendsWith by users directly:

  • io.helidon.microprofile.testing.junit5.HelidonJunitExtension

3rd Party Changes

The new module (io.helidon.microprofile.testing:helidon-microprofile-testing) adds a dependency on net.bytebuddy:byte-buddy. This dependency is already managed in the dependencies BOM.

Documentation

The MicroProfile testing documentation has been updated.

@romain-grecourt romain-grecourt added the 4.x Version 4.x label Jan 25, 2025
@romain-grecourt romain-grecourt added this to the 4.2.0 milestone Jan 25, 2025
@romain-grecourt romain-grecourt self-assigned this Jan 25, 2025
@oracle-contributor-agreement oracle-contributor-agreement bot added the OCA Verified All contributors have signed the Oracle Contributor Agreement. label Jan 25, 2025
@romain-grecourt romain-grecourt removed the request for review from tvallin January 25, 2025 03:12
@romain-grecourt romain-grecourt changed the title Improved Helidon MP testing. 4.x: Improved Helidon MP testing Jan 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
4.x Version 4.x OCA Verified All contributors have signed the Oracle Contributor Agreement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant