Skip to content

Revise convention-based semantics for @TestBean factory methods #32940

Closed
@sbrannen

Description

Overview

If the name of the test bean factory method is not explicitly configured in the @TestBean annotation, a convention-based lookup of the corresponding test bean factory method is performed according to the following semantics.

  • If a method name is not specified, look for exactly one static method named with a suffix equal to "TestOverride" and starting with either the name of the annotated field or the name of the bean (if specified).

However, I assume that many users will likely not wish to be forced to use the TestOverride suffix.

Instead, we should provide greater flexibility in the convention-based approach.

Example

With the status quo, the following example only passes if the factory method is named exactly exampleServiceTestOverride.

@SpringJUnitConfig
class TestBeanConventionTests {

	@TestBean
	ExampleService exampleService;

	static ExampleService exampleServiceTestOverride() {
		return () -> "test";
	}

	@Test
	void test() {
		assertThat(exampleService.greeting()).isEqualTo("test");
	}

	@Configuration
	static class Config {

		@Bean
		ExampleService exampleService() {
			return () -> "prod";
		}
	}

	interface ExampleService {
		String greeting();
	}

}

Proposal

To align with the naming conventions used for @Bean in Spring as well as @MethodSource and @FieldSource in JUnit Jupiter, I propose that we allow test bean factory methods to carry the same name as the annotated @TestBean field by default.

For example, the above test class should pass if we rename the exampleServiceTestOverride() method to exampleService() as follows.

@TestBean
ExampleService exampleService;

static ExampleService exampleService() {
	return () -> "test";
}

Options for Consideration

  1. Support the above Proposal (test bean factory method can be named the same as the annotated field by default).
  2. Remove support for the convention-based suffix altogether.

I think we should go with option 1 in any case, and we should consider option 2.

The rationale for removing support for the TestOverride suffix is that the naming is arbitrary and potentially undesired by users.

  • If users want a default suffix, they could argue that it should rather be TestBean to align with the @TestBean feature's name, or they might think some other suffix would be more suitable. In other words, it will impossible to please all users with a predefined suffix.
  • If users don't like the suffix (and if we don't implement the aforementioned proposal to allow the test bean factory method to have the same name as the field), they will be forced to configure the methodName attribute to avoid use of that suffix.
  • If users want a custom suffix, they can always configure the methodName attribute as they see fit, and if they do, I doubt that many users would choose to use a TestOverride suffix.

Prototype

Implementing support for the above Proposal (consideration option 1) is as simple as adding the following line to TestBeanOverrideProcessor.createMetadata(...).

candidateMethodNames.add(field.getName());

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions