3

It's my first question ever on stackoverflow.com.

Lately I have been looking for a way to change how Spring Boot (2.x) names its beans, created via @Component (etc) annotation.

I have found the SpringApplicationBuilder class, which thankfully allows to inject custom bean name generator:

public class Application {

     public static void main(String[] args) {
        new SpringApplicationBuilder(Application.class)
                .beanNameGenerator(customBeanNameGenerator)
                .run(args);
    }

}

But the problem is, despite the fact that this solution works for production, this does not hovewer work in JUnit 4.0 unit tests, where JUnit Runner SpringRunner recreates Spring Context for testing purposes - in that case SpringApplicationBuilder is not used whatsoever, and as a result our application startup fails, becouse of autowiring multi-beans candidates problems.

@RunWith(SpringRunner.class)
@SpringBootTest(classes= {Application.class} )
public class SomeControllerTest { 
   ... 
}

Is there any elegant way to make that unit tests use SpringApplicationBuilder as well?

Regards.

  • Please add more details: Which annotations do you have on `Application` class? How are you initializing `customBeanNameGenerator`? Which is the root cause of the exception when the tests are run? – Antot Mar 09 '18 at 05:56
  • FYI: the answer from @cisum is correct: the _Spring TestContext Framework_ (loaded via the `SpringRunner`) cannot use configuration provided programmatically via the `SpringApplicationBuilder`. So you have to configure your `BeanNameGenerator` declaratively via an annotation that is picked when loading the test `ApplicationContext`. – Sam Brannen Mar 10 '18 at 16:40
  • I applied the @cirsum (and Sam Brannen) solution (related with using `@ComponentScan` annotation), which solved my problem. Eventually I didn't even have to use my implementation of BeanNameGenerator - I just used [DefaultBeanNameGenerator](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/support/DefaultBeanNameGenerator.html), which seems to name beans as I wanted. By the way: Is forgoing default Spring Bean name generator may inflict in unexpected Spring's autowiring mechanism behaviour? Thanks guys – Fantazjatyk Mar 11 '18 at 13:57

1 Answers1

4

the property "classes" of @SpringBootApplication only use annotations of the classes. therefore the code for building SpringApplication is not work when run the tests.

if you want to fix this problem, you can try other ways such as specify the nameGenerator in @ComponentScan

@ComponentScan(nameGenerator = CustomBeanNameGenerator.class)
public class Application {

 public static void main(String[] args) {
    new SpringApplicationBuilder(Application.class)
            .run(args);
 }

}

ensure you class CustomBeanNameGenerator has an empty constructor.

ps: english is not my native language; please excuse typing errors.

cisum
  • 41
  • 1