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

Duplicate BeanOverrideHandler discovered in @Nested test class hierarchy when upgrading to Spring 6.2.2 #34324

Open
bwaldvogel opened this issue Jan 27, 2025 · 7 comments
Assignees
Labels
in: test Issues in the test module type: regression A bug that is also a regression
Milestone

Comments

@bwaldvogel
Copy link

Consider the following test with nested test classes:

@SpringBootTest
class SomeTest {

    @MockitoSpyBean
    SomeService someService;

    abstract class BaseClassForNestedTests {
        @Test
        void someTest() {}
    }

    @Nested
    class SomeNestedTest extends BaseClassForNestedTests {}
}

@Service
class SomeService {
}

When upgrading Spring Boot 3.4.1 to 3.4.2 (which upgrades Spring from 6.2.1 to 6.2.2), the test starts to fail with:

Duplicate BeanOverrideHandler discovered in test class SomeTest$SomeNestedTest: [MockitoSpyBeanOverrideHandler@5c48c0c0 field = SomeService SomeTest.someService, beanType = SomeService, beanName = [null], strategy = WRAP, reset = AFTER]
java.lang.IllegalStateException: Duplicate BeanOverrideHandler discovered in test class SomeTest$SomeNestedTest: [MockitoSpyBeanOverrideHandler@5c48c0c0 field = SomeService SomeTest.someService, beanType = SomeService, beanName = [null], strategy = WRAP, reset = AFTER]
	at org.springframework.util.Assert.state(Assert.java:101)
	at org.springframework.test.context.bean.override.BeanOverrideContextCustomizerFactory.lambda$findBeanOverrideHandlers$1(BeanOverrideContextCustomizerFactory.java:55)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
	at org.springframework.test.context.bean.override.BeanOverrideContextCustomizerFactory.findBeanOverrideHandlers(BeanOverrideContextCustomizerFactory.java:54)
	at org.springframework.test.context.bean.override.BeanOverrideContextCustomizerFactory.createContextCustomizer(BeanOverrideContextCustomizerFactory.java:46)
	at org.springframework.test.context.bean.override.BeanOverrideContextCustomizerFactory.createContextCustomizer(BeanOverrideContextCustomizerFactory.java:38)
	at org.springframework.test.context.support.AbstractTestContextBootstrapper.getContextCustomizers(AbstractTestContextBootstrapper.java:360)
	at org.springframework.test.context.support.AbstractTestContextBootstrapper.buildMergedContextConfiguration(AbstractTestContextBootstrapper.java:332)
	at org.springframework.test.context.support.AbstractTestContextBootstrapper.buildDefaultMergedContextConfiguration(AbstractTestContextBootstrapper.java:267)
	at org.springframework.test.context.support.AbstractTestContextBootstrapper.buildMergedContextConfiguration(AbstractTestContextBootstrapper.java:215)
	at org.springframework.test.context.support.AbstractTestContextBootstrapper.buildTestContext(AbstractTestContextBootstrapper.java:108)
	at org.springframework.boot.test.context.SpringBootTestContextBootstrapper.buildTestContext(SpringBootTestContextBootstrapper.java:111)
	at org.springframework.test.context.TestContextManager.<init>(TestContextManager.java:142)
	at org.springframework.test.context.TestContextManager.<init>(TestContextManager.java:126)
	at org.springframework.test.context.junit.jupiter.SpringExtension.getTestContextManager(SpringExtension.java:363)
	at org.springframework.test.context.junit.jupiter.SpringExtension.beforeAll(SpringExtension.java:128)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)

I tried to do a search to find if this issue was already reported. I found #34204 which could be related to this issue.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Jan 27, 2025
@sbrannen sbrannen changed the title Duplicate BeanOverrideHandler discovered in test class when upgrading to Spring 6.2.2 Duplicate BeanOverrideHandler discovered in @Nested test class hierarchy when upgrading to Spring 6.2.2 Jan 27, 2025
@sbrannen sbrannen added the in: test Issues in the test module label Jan 27, 2025
@sbrannen sbrannen self-assigned this Jan 27, 2025
@sbrannen
Copy link
Member

What happens if you declare BaseClassForNestedTests as a static nested class or as a stand-alone top-level class?

@sbrannen sbrannen added the status: waiting-for-feedback We need additional information before we can continue label Jan 27, 2025
@sbrannen
Copy link
Member

sbrannen commented Jan 27, 2025

Similarly, what happens if you annotate your non-static nested base class with @NestedTestConfiguration, as follows?

@NestedTestConfiguration(EnclosingConfiguration.OVERRIDE)
abstract class BaseClassForNestedTests {
	// ...
}

Alternatively, you should be able to annotate SomeNestedTest with @NestedTestConfiguration(EnclosingConfiguration.OVERRIDE) to achieve the same effect.

@sbrannen
Copy link
Member

I tried to do a search to find if this issue was already reported. I found #34204 which could be related to this issue.

The change in behavior that you have reported is not related to #34204 but rather results from the changes made to BeanOverrideContextCustomizerFactory and BeanOverrideHandler in conjunction with #33925 (see commit 9181cce for details).

@bwaldvogel
Copy link
Author

bwaldvogel commented Jan 27, 2025

What happens if you declare BaseClassForNestedTests as a static nested class or as a stand-alone top-level class?

This would work, however, in my real-world case I cannot make the base class static.

Similarly, what happens if you annotate your non-static nested base class with @NestedTestConfiguration, as follows?

@NestedTestConfiguration(EnclosingConfiguration.OVERRIDE)
abstract class BaseClassForNestedTests {
	// ...
}

This fixes the error.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Jan 27, 2025
@sbrannen sbrannen removed the status: feedback-provided Feedback has been provided label Jan 27, 2025
@sbrannen
Copy link
Member

This fixes the error.

Thanks for confirming that @NestedTestConfiguration allows you to address that scenario.

In light of that, I am closing this issue as "works as designed".

Cheers,

Sam

@sbrannen sbrannen closed this as not planned Won't fix, can't repro, duplicate, stale Jan 30, 2025
@sbrannen sbrannen added status: invalid An issue that we don't feel is valid and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Jan 30, 2025
@bwaldvogel
Copy link
Author

bwaldvogel commented Jan 30, 2025

Oh, I’m actually surprised to be honest and thought that this behavior change will be addressed. I think from a developer point of view it will be quite surprising and I’m sure that many developers will not know why the exception occurs and how to fix it (i.e. adding the @NestedTestConfiguration(EnclosingConfiguration.OVERRIDE) at the right place).

@sbrannen sbrannen added type: regression A bug that is also a regression and removed status: invalid An issue that we don't feel is valid labels Jan 30, 2025
@sbrannen sbrannen added this to the 6.2.3 milestone Jan 30, 2025
@sbrannen
Copy link
Member

Thanks for the feedback, @bwaldvogel.

Although the current behavior (introduced in 6.2.2) may be considered technically correct in terms of the search algorithm, it is also technically a "regression" in behavior for test bean overrides, and as you mentioned, users may not find it readily apparent how an enclosing class can be visited twice by the search algorithm.

In light of that, I am reopening this issue with the plan to not search in the enclosing class hierarchy of a supertype of a @Nested test class, which should allow your original use case to work without modification.

@sbrannen sbrannen reopened this Jan 30, 2025
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 type: regression A bug that is also a regression
Projects
None yet
Development

No branches or pull requests

3 participants