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

Support bean override features with AOT #32933

Open
sbrannen opened this issue Jun 1, 2024 · 3 comments
Open

Support bean override features with AOT #32933

sbrannen opened this issue Jun 1, 2024 · 3 comments
Assignees
Labels
in: test Issues in the test module theme: aot An issue related to Ahead-of-time processing type: enhancement A general enhancement
Milestone

Comments

@sbrannen
Copy link
Member

sbrannen commented Jun 1, 2024

Overview

Although @MockitoBean and @MockitoSpyBean will not work out-of-the-box within a GraalVM native image due to their dependency on Mockito, the general Bean Override support for tests should ideally work within a native image.

In light of that, we need to ensure that basic usage of @TestBean is supported within a native image, and (if applicable) we will need to document known use cases that are not supported for some reason.

To achieve that, we need to introduce a smoke test application that makes use of @TestBean and verify the expected behavior when the associated tests are run within a native image against Spring Framework 6.2 snapshots or milestones.

We also have to ensure that the necessary runtime hints are registered for the bean override support. For example, we will need tests which verify that reflection hints are registered for the BeanOverrideContextCustomizerFactory, etc.

As a bare minimum, TestContextAotGeneratorIntegrationTests.endToEndTests() must be modified to include test classes that utilize the basic features of @TestBean.

Related Issues

@sbrannen sbrannen added in: test Issues in the test module type: enhancement A general enhancement labels Jun 1, 2024
@sbrannen sbrannen added this to the 6.2.x milestone Jun 1, 2024
@snicoll snicoll added the status: blocked An issue that's blocked on an external project change label Jun 1, 2024
@snicoll snicoll changed the title Support bean override features in a GraalVM native image in the TCF Support bean override features with AOT Jun 1, 2024
@snicoll
Copy link
Member

snicoll commented Jun 1, 2024

I've requalified this issue to investigate how much of these features can be supported by AOT on the JVM and in a native image.

@snicoll snicoll removed the status: blocked An issue that's blocked on an external project change label Jun 11, 2024
@sbrannen sbrannen added the theme: aot An issue related to Ahead-of-time processing label Sep 16, 2024
sbrannen added a commit to sbrannen/spring-framework that referenced this issue Sep 16, 2024
Prior to this commit, AOT processing failed for tests that made use of
test bean override features, since the Set<OverrideMetadata>
constructor argument configured in the bean definition for the
BeanOverrideBeanFactoryPostProcessor could not be handled by our AOT
support.

To address that, this commit registers test bean override
infrastructure beans as singletons instead of via bean definitions with
the infrastructure role.

See spring-projectsgh-32933
sbrannen added a commit to sbrannen/spring-framework that referenced this issue Sep 16, 2024
Prior to this commit, test bean overrides were always created
programmatically and registered as singletons in the bean factory,
alongside "dummy" bean definitions; however, that can lead to issues
during AOT processing and in the AOT runtime, especially for Mockito
based mocks and spies since the "dummy" bean definitions are not real
bean definitions that can be used to create a bean instance in the bean
factory.

To address that, this commit introduces a new
updateOverrideBeanDefinition(BeanDefinition) method in the
OverrideMetadata SPI that allows a concrete OverrideMetadata
implementation to update the BeanDefinition so that it is suitable for
use in AOT -- for example, by registering a static factory method that
is responsible for creating the bean instance.

This commit updates TestBeanOverrideMetadata and DummyOverrideMetadata
in order to verify that this approach could potentially work for
@⁠TestBean and custom bean override implementations. However, this
commit does not attempt to convert the @⁠MockitoBean or
@⁠MockitoSpyBean support to use this approach.

In other words, this commit serves merely as a proof of concept for an
approach that we could consider.

See spring-projectsgh-32933
@sbrannen sbrannen self-assigned this Sep 16, 2024
@sbrannen
Copy link
Member Author

sbrannen commented Sep 16, 2024

In order to get the ball rolling, I started experimenting with AOT/native support for test bean overrides.

Current experimental work on this issue can be viewed in the following feature branch.

There are several issues we will need to address, including, but not limited to, the following.

  • Bean override infrastructure beans must be able to be handled by our AOT processing.
    • With the status quo, we face issues with the Set<OverrideMetadata> constructor argument configured in the bean definition for the BeanOverrideBeanFactoryPostProcessor.
  • Beans created by OverrideMetadata implementations must be able to be handled by our AOT processing.
    • With the status quo, we face issues with the "dummy" bean definitions we create for @MockitoBean and @MockitoSpyBean beans.
  • We currently register "dummy" bean definitions for overridden beans and simultaneously register instances of those beans as singletons; whereas, we should ideally just register proper bean definitions for those beans.

As a side note, we should keep in mind that a ContextCustomizer currently cannot be made "AOT aware", since that can potentially affect how we implement the feature regarding our use of bean definitions and manually registered singletons.

In the first commit on the aforementioned feature branch (sbrannen@b8f69eb), I switched to registering bean override infrastructure beans as singletons instead of via bean definitions with the infrastructure role. I'm not suggesting that's necessarily what we want to do in the end, but doing so allows our @TestBean and @DummyBean tests to work in AOT mode.

In the second commit in that feature branch (sbrannen@102ec94), I introduced a different approach to creating bean override instances which allows a concrete OverrideMetadata implementation to update the override BeanDefinition so that it is suitable for use in AOT -- for example, by registering a static factory method that is responsible for creating the bean instance. I verified this approach works for @TestBean and @DummyBean; however, getting this approach to work for @⁠MockitoBean or @⁠MockitoSpyBean will be significantly more involved.

In any case, we at least now have some topics that we can discuss.

sbrannen added a commit to sbrannen/spring-framework that referenced this issue Sep 17, 2024
This commit introduces a BeanOverrideReflectiveProcessor which
registers runtime hints for any BeanOverrideProcessor configured
via @⁠BeanOverride.

See spring-projectsgh-32933
@sbrannen
Copy link
Member Author

sbrannen commented Sep 17, 2024

In a third commit on my feature branch (sbrannen@fb1caf5), I added support for registering GraalVM native image runtime hints for every BeanOverrideProcessor configured via @BeanOverride.

In addition, I have confirmed that the @TestBean feature works in AOT mode on the JVM as well as in a native image, using 6.2.0-SNAPSHOT builds from the feature branch and Spring Boot 3.4.0-M2.

sbrannen added a commit to sbrannen/spring-framework that referenced this issue Sep 24, 2024
This commit introduces a BeanOverrideReflectiveProcessor which
registers runtime hints for any BeanOverrideProcessor configured
via @⁠BeanOverride.

See spring-projectsgh-32933
sbrannen added a commit to sbrannen/spring-framework that referenced this issue Sep 24, 2024
But create new bean definition for nonexistent bean definitions based
on BeanOverrideFactoryBean.

See spring-projectsgh-32933
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: test Issues in the test module theme: aot An issue related to Ahead-of-time processing type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

2 participants