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

@TestBean factory method resolution is incorrect within class hierarchy #34204

Closed
sbrannen opened this issue Jan 7, 2025 · 1 comment
Closed
Assignees
Labels
in: test Issues in the test module type: bug A general bug
Milestone

Comments

@sbrannen
Copy link
Member

sbrannen commented Jan 7, 2025

Overview

While working on #33925 and #34194, I noticed inconsistencies and peculiarities in the search algorithm for @TestBean factory methods.

Specifically, for a @TestBean field defined in a top-level class, the search for a factory method begins with the current test class (which may be a subclass of or or a @Nested class defined in the class in which the @TestBean field is declared). Whereas, for a @TestBean field defined in a @Nested test class, the search for a factory method begins with the @Nested test class.

The above leads to inconsistent factory method discovery for @TestBean factory methods.

In addition, the algorithm used for top-level classes results in "duplicate bean override" failures for cases which are clearly not duplicates but rather an "override of an override". In other words, a @TestBean declaration in a subclass (which resolves to a factory method in the subclass) currently cannot override a seemingly identical @TestBean declaration in a superclass (which resolves to a factory method in the superclass), which some might consider a bug.

Example

@SpringJUnitConfig
class BaseTests {

	@TestBean
	String enigma;

	static String enigma() {
		return "enigma in superclass";
	}

	@Test
	void test() {
		assertThat(enigma).isEqualTo("enigma in superclass");
	}

	@Nested
	class NestedTests {

		@TestBean
		String enigma;

		static String enigma() {
			return "enigma in nested class";
		}

		@Test
		void test() {
			assertThat(enigma).isEqualTo("enigma in nested class");
		}
	}

	@Configuration
	static class Config {

		@Bean
		String enigma() {
			return "enigma in @Configuration class";
		}
	}
}
class ExtendedTests extends BaseTests {

	@TestBean
	String enigma;

	static String enigma() {
		return "enigma in subclass";
	}

	@Test
	@Override
	void test() {
		assertThat(enigma).isEqualTo("enigma in subclass");
	}
}
  • BaseTests passes as expected.
  • BaseTests.NestedTests currently passes because of the aforementioned inconsistent search algorithm.
  • ExtendedTests fails with the following error.
java.lang.IllegalStateException: Duplicate BeanOverrideHandler discovered in test class example.ExtendedTests: [TestBeanOverrideHandler@2dc3271b field = java.lang.String example.ExtendedTests.enigma, beanType = java.lang.String, beanName = [null], strategy = REPLACE_OR_CREATE, factoryMethod = enigma@ExtendedTests]

The cause of the exception is due to the fact that two @TestBean override handlers resolve the same factory method enigma@ExtendedTests; however, one might expect those to resolve to enigma@BaseTests and enigma@ExtendedTests (i.e., two distinct factory methods).

Proposal

  • Resolve @TestBean factory methods consistently, beginning the search with the declaring class of the @TestBean field.

One downside to the proposal is that @TestBean factory methods would no longer be able to be resolved lazily in subclasses (somewhat like "late binding" to a concrete method), which would be a change in behavior.

Another option is to make the factory method search algorithm for @Nested test classes align with the current semantics for top-level test classes.

Related Issues

@sbrannen sbrannen added in: test Issues in the test module type: bug A general bug labels Jan 7, 2025
@sbrannen sbrannen added this to the 6.2.2 milestone Jan 7, 2025
@sbrannen sbrannen self-assigned this Jan 7, 2025
@sbrannen sbrannen changed the title @TestBean factory method resolution is inconsistent @TestBean factory method resolution is incorrect within class hierarchy Jan 7, 2025
@sbrannen
Copy link
Member Author

sbrannen commented Jan 7, 2025

Team Decision: Consistently resolve @TestBean factory methods beginning the search with the class in which the @TestBean field is declared.

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: bug A general bug
Projects
None yet
Development

No branches or pull requests

1 participant