I have problem when injecting entityManager in my test class. I think that this is because i can't load my spring context in my test class.
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'noteDeFraisDAO': Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.persistence.EntityManagerFactory' available
this is my test class
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {NoteDeFraisTestConfig.class})
#Transactional
#DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
public class NoteDeFraisDAOIT
{
#Autowired
private NoteDeFraisDAO noteDeFraisDAO;
#Test
public void myTest()
{
}
}
And this is the configuration for the test I know that when I use new there will be no inject of entitiesManager define in the dao but I don't know what should I do.
#Configuration
public class NoteDeFraisTestConfig {
#Bean
NoteDeFraisDAO noteDeFraisDAO()
{
return new NoteDeFraisDAO();
}
}
I have tried to set my ContextConfiguration to my applicationContext but it didn't work I think that it is because the directory WEB-INF doesn't belong to the classpath. How can I fix this??
This is the structure of my project
thanks.
Update
this is my final test class
#WebAppConfiguration
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration({"file:web/WEB-INF/applicationContext.xml", "file:web/WEB-INF/db-config.xml","file:web/WEB-INF/dispatcher-servlet.xml","file:web/WEB-INF/security-config.xml"})
#Transactional
public class NoteDeFraisDAOIT
{
#Autowired
private NoteDeFraisDAO noteDeFraisDAO;
#Test
public void myTest()
{
}
}
Yep, the problem is that the ApplicationContext loaded for your test does not contain the LocalContainerEntityManagerFactoryBean. Assuming that's declared properly in applicationContext.xml, the linked solution below will help.
I have tried to set my ContextConfiguration to my applicationContext but it didn't work I think that it is because the directory WEB-INF doesn't belong to the classpath. How can I fix this??
That's covered here: Location of spring-context.xml
Related
I have a SpringBoot application, basically with a structure similar to the following:
application:
#SpringBootApplication
public class MyApplication {
#Autowired
MainService mainService;
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
#KafkaListener(topics = "myTopic")
public void listen(String message) {
this.graphicService.performWork();
}
}
first service:
#Service
public MainService {
#Autowired MyService myService;
public performWork() {
this.myService.doStuff();
}
}
second service:
#Service
public class MyService {
// server.param1 and server.param2 are defined in application.properties file
#Value("${server.param1}")
private String param1;
#Value("${server.param2}")
private String param2;
#PostConstruct
public void initService(){
}
public void doStuff() {
// do stuff assuming the parameters param1 and param 2 of this autowired service have already been initialized
}
}
I have a junit like the following:
#SpringBootTest(classes = MyApplication.class)
class MyServiceTest {
#Test
void testMyService() {
MyService myService = new MyService();
myService.doStuff();
}
}
When I execute testMyService, I get an exception thrown, essentially like this:
java.lang.IllegalStateException: Failed to load ApplicationContext
.
.
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'myApplication': Unsatisfied dependency expressed through field 'mainService';
.
.
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'mainService': Unsatisfied dependency expressed through field 'myService'
.
.
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myService': Injection of autowired dependencies failed
.
.
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'server.param1' in value "${server.param1}"
The application works fine operationally. I thought that the way I set up the junit, the springboot app would simply fire up and the parameters found in the application.properties file would simply be available to MyService service as are they when I run the application itself (not the junit).
Obviously I am doing something wrong, and the application context is not available the way I have this junit set up. I would be grateful for any ideas for getting this to work properly.
Thanks!
Wire your class under test in the Junit test like in any production code class.
The #SpringBootTest will autodetect the #SpringBootApplication, so no extra parameter is needed. Just wire the needed dependencies like you would in the application classes.
The test will use the src/test/resources/application.properties (or yml) file, if present. If not present, the src/main/resources/application.properties is used. So if you use environment variables in your production application.yml copy this file to the test resources and fill the parameters with dummy parameters for test.
#SpringBootTest
class MyServiceTest {
#Autowired MyService myService;
#Test
void testMyService() {
myService.doStuff();
}
}
If you like you can add the parameters in the test class with #TestPropertySource(properties
#SpringBootTest
#TestPropertySource(properties = {
"server.param1=srv1",
"server.param2=srv2"
})
class MyServiceTest {
...
Make sure you have spring-boot-starter-test in your dependencies.
Maven Example:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.7.5</version>
<scope>test</scope>
</dependency>
I created an Embedded Sftp server bean for my integration tests, i hooked the startup and the shutdown of the server respectively with the afterPropertiesSet and destroy life cycles
public class EmbeddedSftpServer implements InitializingBean, DisposableBean {
//other class content
#Override
public void afterPropertiesSet() throws Exception {
//Code for starting server here
}
#Override
public void destroy() throws Exception {
//Code for stopping server here
}
}
here my config class
#TestConfiguration
public class SftpTestConfig {
#Bean
public EmbeddedSftpServer embeddedSftpServer() {
return new EmbeddedSftpServer();
}
//Other bean definitions
}
Now when i inject the bean in my test classes like the following :
#ExtendWith(SpringExtension.class)
#ContextConfiguration(classes = SftpTestConfig .class)
class ExampleOneIT {
#Autowired
private EmbeddedSftpServer embeddedSftpServer;
}
#ExtendWith(SpringExtension.class)
#ContextConfiguration(classes = SftpTestConfig .class)
class ExampleTwoIT {
#Autowired
private EmbeddedSftpServer embeddedSftpServer;
}
#SpringBatchTest
#ContextConfiguration(classes = SftpTestConfig .class)
class ExampleThreeIT {
#Autowired
private EmbeddedSftpServer embeddedSftpServer;
}
And i run all the test classes simultaneously, i found out that for the test classes annotated with #ExtendWith(SpringExtension.class), it's the same context that is used (which is understandable since i guess spring cache it) and therefore the bean lifecycle methods are not executed again, but to my surprise, for the class annotated with #SpringBatchTest i noticed that the life cycle hooks of the bean are executed again! Which is a behavior that is not convenient since i want the application context to start the server one time for all tests and close it at the end of those tests (which is the case if i use only #ExtendWith(SpringExtension.class) for all my test classes).
N.B. : I need to use #SpringBachTest for my ExampleThreeIT test class.
I think you are hitting this issue: https://github.com/spring-projects/spring-batch/issues/3940 which has been fixed in v4.3.4/4.2.8. Upgrading to one of these versions should fix your issue.
We have written below 2 classes
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {TestConfig.class})
public class AbcFilterTest {
#Autowired
private AbcUtils abcUtils;
#Autowired
private AbcRepository abcRepository;
#Test
public void testFilter() {
MockHttpServletRequest httpServletRequest = new MockHttpServletRequest();
MockHttpServletResponse httpServletResponse = new MockHttpServletResponse();
MockFilterChain mockChain = new MockFilterChain();
}
}
#Configuration
#ComponentScan(basePackageClasses = {AbcUtils.class, AbcRepository.class,})
public class TestConfig {
}
For running a test class, i need instance of both AbcUtilsclass and AbcRepository interface(extending CurdRepository) which are autowired in the class i am testing.1st one has #Component while 2nd has #Repositry on top of it.As you can see,in my test class I have autowired both util and repository class with component scan as above code.In real time spring framework creates implementaion class for the repository interface but On running test case,I am getting below error
Caused by: org.springframework.beans.BeanInstantiationException:
Failed to instantiate [com.a.b.c.persistence.AbcRepository]: Specified
class is an interface.
Kindly suggest how to make this test class work. Please note that we are not using Spring Boot and Mockito.We are doing integration testing.
We are using Spring rest and Spring Data JPA with hibernate.
Scanning AbcUtils.class and AbcRepository.class is not enough if you want to write something in the database. You need to scan the configuration that contains your DataSource definition and related config. Since the tests will be instantiated like a Spring bean too, the test class need to implement the ApplicationContextAware interface:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"/config.xml"})
public class TestClass implements ApplicationContextAware{
#Autowired
Repository repository;
//....
}
I have a set of Integration Tests running for my Spring-Boot 1.3 app. But I had to add the following to get my maximum sessions working:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter implements ServletContextAware {
...
#Override
public void setServletContext(ServletContext servletContext) {
servletContext.getSessionCookieConfig().setHttpOnly(true);
// causes an ApplicationEvent to be published to the Spring ApplicationContext every time a HttpSession commences or terminates
servletContext.addListener(new HttpSessionEventPublisher());
}
...
}
Now when I run my tests, I get the following:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'webSecurityConfig' defined in file [/Users/davidclark/projects/edmtotal/build/classes/main/com/edelweissco/dental/configuration/WebSecurityConfig.class]: Initialization of bean failed; nested exception is java.lang.UnsupportedOperationException
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
...
Caused by: java.lang.UnsupportedOperationException
at org.springframework.mock.web.MockServletContext.addListener(MockServletContext.java:675)
at com.edelweissco.dental.configuration.WebSecurityConfig.setServletContext(WebSecurityConfig.java:123)
...
Here is an example test class (but they all fall with the same exception):
#Transactional
public class ConfigurationSettingsTest extends BaseSpecification {
#Autowired
private ConfigurationSettings configurationSettings;
#Autowired
ConfigurableApplicationContext context
...
}
where BaseSpecification is:
#ContextConfiguration(classes = MyApp, loader = SpringApplicationContextLoader)
#WebAppConfiguration
public class BaseSpecification extends Specification {
#Value('${local.server.port}')
private int serverPort;
def setup() {
RestAssured.port = serverPort;
}
}
It would seem that now when I run my integration tests, a MockServlet is being applied here, and it doesn't support. this feature. When debugging, I see that a SpringBootMockServletContext is trying to be set in setServletContext, and that is where the exception is.
I will post my answer in case anyone else runs into this. The problem was in my BaseSpecification. I added the #WebAppConfiguration and #IntegrationTest to it, and removed #IntegrationTest off the individual integration tests. Apparently this will actually create the ServletContext the way it should be.
#ContextConfiguration(classes = MyApp, loader = SpringApplicationContextLoader)
#WebAppConfiguration
#IntegrationTest
public class BaseSpecification extends Specification {
This question was asked before Using Autowired in a TestExecutionListener class for BeforeClass junit however it wasn't answered. I am facing the same problem but haven't figured out the solution
Example: I am getting null mapper.
public class CustomExecutionListener extends AbstractTestExecutionListener {
#Autowired
private Mapper mapper;
#Override
public void beforeTestClass(TestContext testContext) {}
... some code...
}
Test Class: Note: AppConfig contains the Mapper Bean defined.
#RunWith(SpringJUnit4ClassRunner.class)
#TestExecutionListeners(listeners = {DependencyInjectionTestExecutionListener.class, CustomExecutionListener.class})
#ContextConfiguration(classes = {AppConfig.class})
public class AccountControllerTest {
....
}
Dependency injection is not supported for TestExecutionListener instances.
Dependency injection is only supported for test instances.
Thus, if your CustomExecutionListener needs to access a bean from the ApplicationContext, it will have to look it up manually -- for example, like this:
public void beforeTestClass(TestContext testContext) {
Mapper mapper = testContext.getApplicationContext().getBean(Mapper.class);
// ... some code...
}
Regards,
Sam (author of the Spring TestContext Framework)
You can also try this: Mapper mapper = Mappers.getMapper(Mapper.class);