Revise convention-based semantics for @TestBean
factory methods #32940
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
- Support the above Proposal (test bean factory method can be named the same as the annotated field by default).
- 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 aTestOverride
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());