This question already has an answer here:
Why autowiring spring repositories doesn't work?
(1 answer)
Closed 2 years ago.
I've a test class which autowires the CatalogDao class. But the CatalogDao class is not autowired. The value is null;
Test class
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {PersistenceConfig.class})
public class CatalogDaoIT {
#Autowired
private CatalogDao catalogDao;
#Test
public void saveCatalog_readSame_foundOne() {
// arrange
Catalog catalog = new Catalog();
Config class
package ch.matica.platform.persistence.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
#Configuration
#PropertySource("classpath:application.properties")
#ComponentScan(basePackages = "ch.matica.platform.persistence")
public class PersistenceConfig {
#Bean
public static PropertySourcesPlaceholderConfigurer propertiesResolver() {
return new PropertySourcesPlaceholderConfigurer();
}
}
The DAO class
package ch.matica.platform.persistence;
import java.util.Collection;
...
#Repository
public class CatalogDao {
...
Can you change your code to this:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {PersistenceConfig.class})
public class CatalogDaoIT {
#Autowired
private CatalogDao catalogDao;
//autowire by type, a private field and a setter
#Autowired
public void setCatalogDao(CatalogDao cd){
this.catalogDao=cd;
}
#Test
public void saveCatalog_readSame_foundOne() {
// arrange
Catalog catalog = new Catalog();
I think this will help.
For me this worked
#SpringBootTest
public class CatalogDaoIT {
....
}
Related
spring 5.1.9-RELEASE
spring boot 2.1.7-RELEASE
when i has internal class to register ,i use #EnableConfigurationProperties marks on class A and B ,at this time has happen exception; i remove the class A annotation;at this time started successful;
the class B use #EnableConfigurationProperties registering C,at this time B is also registered,the classB should b be registered at this time ?
But when I move the two internal classes to the same path as TestConfiguration, both class A and class B have to be #EnableConfigurationProperties annotated to complete the startup
package com.test.configuration;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.test.configuration.TestConfiguration.TestConfigB;
import lombok.Data;
#Configuration
#EnableConfigurationProperties(TestConfigB.class)
public class TestConfiguration {
#Bean
#ConditionalOnMissingBean(TestConfigA.class)
#ConditionalOnProperty(prefix = "test-a", name = "enable", havingValue = "true", matchIfMissing = true)
public TestConfigA testConfigA(TestConfigB testConfigB) {
return new TestConfigA();
}
#Data
public class TestConfigA {
private String name;
}
#Data
#ConfigurationProperties(prefix = "test-b")
#EnableConfigurationProperties(TestConfigC.class)
public class TestConfigB {
private String applicationId;
#Autowired
TestConfigC axxcConfig;
public String getApplicationId() {
if (applicationId == null) {
applicationId = axxcConfig.getApplicationId();
}
return applicationId;
}
}
#ConfigurationProperties(prefix = "test-c")
public class TestConfigC implements ApplicationContextAware {
private String applicationId;
private ApplicationContext applicationContext;
public String getApplicationId() {
if (applicationId == null) {
applicationId = applicationContext.getEnvironment().getProperty("spring.application.name");
}
return applicationId;
}
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
}
Your #ConfigurationProperties classes need to be static so that copies of them can be created independently of (before) the containing configuration class.
I'm trying to autowire an attribute (myService) which is tagged as a #Service, inside a #Configuration class, but I get a NullPointer.
If instead, I autowire myService in non-configuration classes, I have no issues.
Here's the #Service I'm having issues autowiring:
package com.myapp.resources;
#Service
class MyService {
public List<String> getRoutingKeys() {
List<String> routingKeys;
//Do stuff
return routingKeys;
}
public String aMethod() {
return "hello";
}
}
Here's the #Configuration class where I can't autowire the Service
package com.myapp.messaging;
import com.myapp.resources;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.List;
#Configuration
public class RabbitConfiguration {
private List<String> routingKeys = writeRoutingKeys();
#Autowired
private MyService myService;
private List<String> writeRoutingKeys() {
boolean test = myService == null;
System.out.println("is the service null? " + test); //output: true!!!
return myService.getRoutingKeys(); //here I get a NullPointer
}
//Methods with bean declarations for RabbitMQ
}
If it helps, here's my mainclass:
package com.myapp;
import com.myapp.resources;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import java.util.List;
#SpringBootApplication
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext appContext = SpringApplication.run(Application.class, args);
MyService myService = (MyService) appContext.getBean(MyService.class);
boolean test = myService == null;
System.out.println("is the service null? " + test); //output: false
//Do stuff
}
}
If it helps, here's a different class (a #RestController) where I'm able to autowire the service
package com.myapp.resources;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class MyController {
#Autowired
private MyService myService;
#GetMapping("/endpoint")
public String myRestMethod() {
boolean test = myService == null;
System.out.println("is the service null? " + test); //output: false
return myService.aMethod();
}
}
I've also tried adding the #ComponentScan in the Configuration class, but I still get a NullPointer
package com.myapp.messaging;
//list of imports...
#Configuration
#ComponentScan("com.myapp.demo")
public class RabbitConfiguration {
#Autowired
private MyService myService;
//...
}
Spring will only inject the dependencies after or when a bean is instantiated (Depending if constructor injection is used or not). However , you are now accessing the dependency MyService during the field initialisation which happens before initialising a bean .Hence , it cannot access MyService during field initialisation as it is not injected yet.
You can simply fix it by changing to use constructor injection and initialise routingKeys inside a constructor at the same time :
#Configuration
public class RabbitConfiguration {
private List<String> routingKeys ;
private MyService myService;
#Autowired
public RabbitConfiguration(MyService myService){
this.myService = myService
this.routingKeys = writeRoutingKeys();
}
private List<String> writeRoutingKeys() {
return myService.getRoutingKeys();
}
}
Or simply :
#Autowired
public RabbitConfiguration(MyService myService){
this.myService = myService
this.routingKeys = myService.getRoutingKeys();
}
I would suggest injecting the service through any #Bean creation method that needs it:
#Bean
public MyBean create(MyService myService)
and then pass the service into the writeRoutingKeys(MyService myService) method to process it accordingly.
Per documentation:
#Configuration classes are processed quite early during the
initialization of the context and forcing a dependency to be injected
this way may lead to unexpected early initialization. Whenever
possible, resort to parameter-based injection as in the example above.
I want to write test cases for service layer of spring framework using Junit + Mockito.
How to call the actual service layer method using my ServiceTest class, If i mock the ServiceTest class then it's object wont execute the actual service method code because it wont get the object to call it's methods and if I try with the Spy still it was not working, I tried this example
still I not able to execute the test cases.
MyService.java
#Service
public class MyService{
#Autowired
Utility utility;
public String showResult(){
String result = utility.getName();
return result;
}
}
MyServiceTest.java
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(loader=AnnotationConfigWebContextLoader.class)
#WebAppConfiguration
public class MyServiceTest {
#Autowired
MyService myService;
#Autowired
Utility utility;
#Test
public void testShowResult() throws Exception {
assertEquals("Test",myService.showResult());
}
#Configuration
static class MykServiceTestContextConfiguration {
#Bean
public MyService myService() {
return new MyService();
}
#Bean
public Utility utility() {
return Mockito.mock(Utility.class);
}
}
}
You have to first mock the Utility class and then have to invoke it before calling your #Test using MockitoAnnotations.initMocks(this) as follows:
MyServiceTest.java
import static org.mockito.Mockito.when;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.AnnotationConfigWebContextLoader;
import org.springframework.test.context.web.WebAppConfiguration;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(loader = AnnotationConfigWebContextLoader.class)
#WebAppConfiguration
public class MyServiceTest {
#InjectMocks
private MyService myService;
#Mock
private Utility utility;
#Before
public void setupMock() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testShowResult() throws Exception {
when(utility.getName()).thenReturn("Test");
Assert.assertEquals("Test", myService.showResult());
}
#Configuration
static class MykServiceTestContextConfiguration {
#Bean
public MyService myService() {
return new MyService();
}
#Bean
public Utility utility() {
return new Utility();
}
}
}
MyService.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#Service
public class MyService {
#Autowired
private Utility utility;
public String showResult() {
String result = utility.getName();
return result;
}
}
Utility.java
import org.springframework.stereotype.Component;
#Component
public class Utility {
public String getName() {
return "hello";
}
}
Make use of #Spy
When spy is called, then actual method of real object is called.
https://www.tutorialspoint.com/mockito/mockito_spying.htm
please go through the tutorial
This worked for me
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration
#WebAppConfiguration
public class MyServiceTest {
#Spy
MyService myService;
#Test
public void testShowResult() throws Exception {
assertEquals("Test",myService.showResult());
}
#Service
public class MyService{
public String showResult(){
return "Test";
}
}
}
still having issues share the spring version you are using
How about using #MockBean? It suits Spring + JUnit and, probably you need to implement mock behavior.
I guess that Utility.getName() return "Test" in the test case.
The following is the test code I tried.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(loader = AnnotationConfigWebContextLoader.class)
#WebAppConfiguration
public class MyServiceTest {
#Autowired
MyService myService;
#MockBean
Utility utility;
#Test
public void testShowResult() throws Exception {
Mockito.when(utility.getName()).thenReturn("Test");
assertEquals("Test", myService.showResult());
}
#Configuration
static class MykServiceTestContextConfiguration {
#Bean
public MyService myService() {
return new MyService();
}
}
}
I want to create a DAO object by dependency injection (#Autowire) but unfortunately, this DAO object is never created and hence a Nullpointer exception is thrown.
This is my DAO implementation:
package com.sample.dao.service;
#Component
public class OrderServiceImpl implements OrderService {
private final OrderRepository orderRepository;
#Autowired
OrderServiceImpl(OrderRepository orderRepository) {
this.orderRepository = orderRepository;
}
#Override
public void save(Order order) {
return orderRepository.save(order);
}
The class where the Nullpointer exception is caused:
package com.sample.dispatcher;
#Component
public class OrderDispatcher {
private final OrderServiceImpl orderServiceImpl;
#Autowired
public OrderDispatcher(OrderServiceImpl orderServiceImpl) {
this.orderServiceImpl = orderServiceImpl;
}
public void createOrder(Order order) {
orderServiceImpl.save(order)); // --> Nullpointer
My entry class:
package com.sample;
#SpringBootApplication
#ComponentScan(basePackages = { "com.sample" , "com.webservice"})
#EnableJpaRepositories(basePackages = "com.sample.dao.repository")
public class Application {
public static void main(final String[] args) {
SpringApplication.run(Application.class, args);
I think you should change your constructor to have an argument type of interface rather than a concrete implementation. So something like this -
#Component
public class OrderDispatcher {
private final OrderService orderServiceImpl;
#Autowired
public OrderDispatcher(OrderService orderServiceImpl) {
this.orderServiceImpl = orderServiceImpl;
}
When you add the #component notation on OrderServiceImpl, Spring creates proxy for that class and it can be autowired by interface.
Maybe you forgot the #annotation configuration. Try adding this class and also you scan your entities: EntityScan
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
#Configuration
#EntityScan("com.sample.model") // Your model package
#ComponentScan(basePackages = { "com.sample" , "com.webservice"})
#EnableJpaRepositories(basePackages = "com.sample.dao.repository")
public class RepositoryConfig {
}
AppConfig contains Java Configuration.
package com.wh;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableLoadTimeWeaving;
import org.springframework.context.annotation.EnableLoadTimeWeaving.AspectJWeaving;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.aspectj.EnableSpringConfigured;
#Configuration
#EnableSpringConfigured
#EnableLoadTimeWeaving(aspectjWeaving=AspectJWeaving.ENABLED)
public class AppConfig {
#Bean
#Lazy
public EchoService echoService(){
return new EchoService();
}
#Bean
public InstrumentationLoadTimeWeaver loadTimeWeaver() throws Throwable {
InstrumentationLoadTimeWeaver loadTimeWeaver = new InstrumentationLoadTimeWeaver();
return loadTimeWeaver;
}
}
Service Class
package com.wh;
import org.springframework.stereotype.Service;
#Service
public class EchoService {
public void echo( String s ) {
System.out.println( s );
}
}
EchoDelegateService is the Non Bean class in which we have Autowired The required Bean.
We expect that the EchoService should get autowired.
Problem : EchoService not getting autowired. Gives an Null Pointer exception.
package com.wh;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
#Configurable( preConstruction = true, autowire = Autowire.BY_TYPE, dependencyCheck = false )
public class EchoDelegateService {
#Autowired
private EchoService echoService;
public void echo( String s ) {
echoService.echo( s );
}
}
Main Class where we are calling method of NonBean Class.
package com.wh;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MainApp {
public static void main(String[] args) {
ApplicationContext ctx =
new AnnotationConfigApplicationContext(AppConfig.class);
new EchoDelegateService().echo("hihi, it works...");
}
}
Your question already includes the answer: "... in a non-bean class". This simply does not work. All the autowiring, aspect resolving and whatever is to that, only works for beans. Thus, you definitely need to construct your EchoDelegateService via the spring factory:
EchoDelegateService myService = ctx.getBean(EchoDelegateService.class);
myService.echo("this should really work now");