IntelliJ Idea + Could not autowire. No beans of type found - spring-boot

I keep seeing below error in my IntelliJ Idea, however the code works fine during execution.
Could not autowire. No beans of 'PortfolioRequestHandler' type found. less... (Ctrl+F1)
Inspection info:Checks autowiring problems in a bean class.
Sample Code
#ActiveProfiles("test")
#RunWith(SpringRunner.class)
#DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
#SpringBootTest(classes = {Application.class})
public class PortfolioRequestHandlerTest {
#Autowired
private PortfolioRequestHandler portfolioRequestHandler;
...
...
}
How do I get rid of this? I am using IntelliJ Idea ULTIMATE 2018.2

Are you sure that your Spring beans are wired correctly and that it's an IDE problem?
check if your PortfolioRequestHandler class is annotated with #Service, #Component or #Repository (bean config via component scanning)
otherwise check if your bean is wired in a #Configuration annotated class -> in that case there should be a method that returns an instance of type PortfolioRequestHandler and that's annotated with #Bean
try adding a configuration class (as mentioned in 2.) and add this class to your #SpringBootTest(classes = {...} annotation; see example below
#Configuration
public class CustomBeanConfig {
#Bean
public PortfolioRequestHandler get PortfolioRequestHandler() {
return new PortfolioRequestHandler();
}
}
#SpringBootTest(classes = {Application.class, CustomBeanConfig.class})
have a look at this one, maybe helps: https://stackoverflow.com/a/50267869/150623

Related

How to exclude classes with #Configuration in #SpringBootApplication testing

I am using a dependent module called spring-cloud-aws. It has a #Configuration class as org.springframework.cloud.aws.messaging.config.annotation.SqsConfiguration
In my SpringBoot JUnit test case the SqsConfiguration class is getting detected and Beans are getting initialized. I want to exclude this Configuration in class in my JUNit test case. How to achieve this ?
I tried using #ComponentScan it didn't work.
#RunWith(SpringRunner.class)
#SpringBootTest(classes = SQLTestConfig.class)
#ActiveProfiles("test")
public class BusinessManagerTest {
}
#TestConfiguration
#ComponentScan(basePackages = {"package1","package1"},
excludeFilters = {#ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = SqsConfiguration.class)})
#Profile("test")
class SQLTestConfig {
#Bean
public SomeBean beans() {
return new SomeBean();
}
}
Loading this configuration class requires aws credentials to be available. I don't want to inject credentials for running a simple Bean test case.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'simpleMessageListenerContainer' defined in class path resource [org/springframework/cloud/aws/messaging/config/annotation/SqsConfiguration.class]: Invocation of init method failed; nested exception is com.amazonaws.services.sqs.model.AmazonSQSException: The security token included in the request is expired
There are multiple ways to exclude specific auto-configuration during testing:
exclude via properties in your application-test.properties
spring.autoconfigure.exclude=org.springframework.cloud.aws.messaging.config.annotation.SqsConfiguration
exclude via #TestPropertySource:
#RunWith(SpringRunner.class)
#ActiveProfiles("test")
#SpringBootTest(classes = SQLTestConfig.class)
#TestPropertySource(properties ="spring.autoconfigure.exclude=org.springframework.cloud.aws.messaging.config.annotation.SqsConfiguration")
exclude via #EnableAutoConfiguration, e.g.:
#RunWith(SpringRunner.class)
#ActiveProfiles("test")
#SpringBootTest(classes = SQLTestConfig.class)
#EnableAutoConfiguration(exclude=SqsConfiguration.class)
Choose one that suites you better ;)
So to disable the auto-loading of all Beans for a Test, the test class can explicitly mention the dependencies required. This can be done using ContextConfiguration annotation. eg,
#ExtendWith(SpringExtension.class)
#ContextConfiguration(classes = {EmployeeService.class})
public class EmployeeLeavesTest {
#Autowired
private EmployeeService employeeService;
}
In this eg, only EmployeeService class will be available and other beans will not be loaded.

Load 1 bean from #configuration in SpringBoot

PIDClient has HttpClient (Java 11) as a dependency in its constructor. I want to autowire this so I created an #Configuration annotated class named SpringConfiguration. I got it working with the code below.
#RunWith(SpringRunner.class)
#SpringBootTest(classes = {PIDClient.class, SpringConfiguration.class})
public class PIDClientTest {
My issue with this is, now it loads all the beans in SpringConfiguration while I only need HttpClient bean. I tried the code below but that gave me a No qualifying bean of type 'java.net.http.HttpClient'.
#RunWith(SpringRunner.class)
#SpringBootTest(classes = {PIDClient.class, HttpClient.class})
public class PIDClientTest {
Here's a screenshot of the projects' directory structure in case it's needed with the relevant classes open.
Is there a better way?

Spring inject test: Bean is not injected on test

I've created this custom test configuration:
#TestConfiguration
public static class RestTemplateTestConfiguration {
#Bean
#Primary
public static ApplicationDao applicationDao() {
ApplicationDao mock = Mockito.mock(ApplicationDao.class);
// some stuff code
return mock;
}
}
I've set a breakpoint on applicationDao, but it's never reached, and therefore mock is never injected.
EDIT
ApplicationDao is an #Repository annotated class:
#Repository
public interface ApplicationDao extends MongoRepository<Application, String> {
So, how could I override this #Repository annotated AplicationDao?
Currently, I'm getting this message when spring starts:
Skipping bean definition for [BeanMethod:name=applicationDao,declaringClass=net.gencat.transversal.espaidoc.functional.references.GroupReferencesTest$RestTemplateTestConfiguration]: a definition for bean 'applicationDao' already exists. This top-level bean definition is considered as an override.
Any ideas?
If your method applicationDao() is never called it means that your spring boot is not scanning the package where RestTemplateTestConfiguration is located.
The simplest solutions is to move the configuration under the same package (or its children) as the one that contains the class annotated with #SpringBootApplication.
OBS : This rule applies even though the configuration is in the test directory instead of main.
Another solution is to add #ComponentScan with the configuration package or to use #Import(RestTemplateTestConfiguration.class) at your spring boot test level.
SUGGESTION:
For your problem you can use:
#Mock
ApplicationDao applicationDao;
and if you have another service that uses this one to use:
#InjectMock
MyService myService;

Prevent Application / CommandLineRunner classes from executing during JUnit testing

If in your TestCase class there is this annotations:
#SpringApplicationConfiguration(classes = {Application.class})
this will cause the Application.class, implementing the CommandLineRunner interface, to run the required method
public void run(String... args) throws Exception
I still think this is, mostly, a not wanted behaviour, since in your test environment you may not want to launch the entire application.
I have in mind two solution to circumvent this problem:
to remove the CommandLineRunner interface from my Application class
to have a different context for testing
Both this solution requires lot of coding.
Do you have a more convenient solution?
Jan's solution can be achieved easier.
In your test class, activate the "test" profile:
#RunWith(SpringJUnit4ClassRunner.class)
#ActiveProfiles("test")
public class MyFancyTest {}
In your CommandLineRunner set the profile to NOT test:
#Component
#Profile("!test")
public class JobCommandLineRunner implements CommandLineRunner {}
Then you don't have to manually set the profile in the Application.
As mentioned in the spring documentation you can use #ContextConfiguration with a special initializer:
ConfigDataApplicationContextInitializer is an ApplicationContextInitializer that you can apply to your tests to load Spring Boot application.properties files. You can use it when you do not need the full set of features provided by #SpringBootTest
In this example anyComponent is initialized and properties are injected, but run(args) methods won't be executed. (Application.class is my main spring entry point)
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = Application.class,
initializers = ConfigDataApplicationContextInitializer.class)
public class ExtractorTest {
#Autowired
AnyComponent anyComponent;
#Test
public void testAnyComponent() {
anyComponent.anyMethod(anyArgument);
}
}
You can define a test configuration in the same package as your application that looks exactly the same, except that it excludes beans implementing CommandLineRunner. The key here is #ComponentScan.excludeFilters:
#Configuration
#ComponentScan(excludeFilters = #ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = CommandLineRunner.class))
#EnableAutoConfiguration
public class TestApplicationConfiguration {
}
Then, just replace the configuration on your test:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest(classes = TestApplicationConfiguration.class)
public class SomeApplicationTest {
...
}
No CommandLineRunner will be executed now, because they are not part of the configuration.
I'm a bit late to the party, but a reasonable approach is to mark the bean with #ConditionalOnProperty, e.g.
#ConditionalOnProperty(prefix = "job.autorun", name = "enabled", havingValue = "true", matchIfMissing = true)
public CommandLineRunner myRunner() {...}
The following annotation will then disable it in tests:
#SpringBootTest(properties = {"job.autorun.enabled=false"})
If you have a mocking framework installed (e.g. MockMVC) you can create a mock instance of the CommandLineRunner implementation, more or less disabling it:
#MockBean
private TextProcessor myProcessor;
Previous answers didn't work wor me. I ended up using different profiles - example for the init method in Spring Boot:
SpringApplication app = new SpringApplication(AppConfig.class);
app.setAdditionalProfiles("production");
app.run(args);
This is not executed during the tests so we're safe here.
All tests have their own profile "test" (which is useful in many other ways, too):
#RunWith(SpringJUnit4ClassRunner.class)
#ActiveProfiles("test")
public class MyFancyTest {}
The command-line runner is annotated with the "production" profile so the tests ignore it:
#Component
#Profile("production")
public class JobCommandLineRunner implements CommandLineRunner {}
I solve this by not implementing CommandLineRunner. Just get a bean from the context, and call a method on it, passing argv. That way you will get the same result, and the application won't start automatically when running the tests.

Use #Primary to precede an #Component/#Service annotated class

In my project I have a service with the #Service annotation.
#Service
public class ExampleService { ... }
I would like to override this service with a Mockito-mock, using a configuration file for my test in the following way:
public class TestContext{
#Bean
#Primary
public ExampleService exampleService(){
return mock(ExampleService.class);
}
}
and in my test class:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = { WebContext.class, TestContext.class})
#WebAppConfiguration
public class TestExample{...}
For some reason the mocks aren't injected. The only way I can make this work is when I don't use #Service (#Component gives the same problem) but use a bean annotated method in the WebContext to load the ExampleService, and I put the TestClass behind the WebContext.class in the ContextConfiguration annotation (like in the code I wrote here). I don't get why, and I would like to know how I can keep using the #Service annotation.

Resources