How to use the SpringBoot's context for testing by JerseyTest - java

I have some #Component and #Resource in my SpringBoot application.
I have the right JDBC datasource, and also I have some REST services, by Jersey.
I want to test one of the services, but it will fail, it says:
Injection of autowired dependencies failed
But it does not use any component.
This is a simple test for testing db, and it is working:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = MyApplication.class)
public class CommonRepositoryTest {
#Autowired
private MyRepository myRepository;
#Test
public void testDatabaseChangeLogsSize() {
int resultSize = myRepository.getTableRowSize(MyTable.TABLE_NAME);
System.out.println("MyTable result list size: "+resultSize);
assertTrue("MyTable table should has at least one row!", resultSize>0);
}
}
But this REST tester is not working:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = MyApplication.class)
public class SampleResourceTest extends JerseyTest {
#Override
protected Application configure() {
ApplicationContext context = new AnnotationConfigApplicationContext(MyApplication.class);
return new ResourceConfig(SampleResource.class).property("contextConfig", context);
}
#Test
public void testSampleGet() throws Exception {
long id = 1;
String name = "name";
SampleDomainModel sampleDomainModel = new SampleDomainModel();
sampleDomainModel.setId(id);
sampleDomainModel.setName(name);
Response response = target("/sampleresource/samplepath/" + id).queryParam(name).request().get(Response.class);
SampleDomainModel responseSampleDomainModel = response.readEntity(SampleDomainModel.class);
assertEquals(sampleDomainModel.getId(), responseSampleDomainModel.getId());
}
}
As you see, it must override the configure() method from JerseyTest.
I think the problam is, that the AnnotationConfigApplicationContext cannot load anything maybe (?).
The #SpringApplicationConfiguration(classes = MyApplication.class) annotation loads the context, but the new AnnotationConfigApplicationContext(MyApplication.class) code maybe do the failure, it does not have the full context.
If I replace the code with mocking, it works (but it is not a nice way):
#Override
protected Application configure() {
ApplicationContext mockContext = Mockito.mock(ApplicationContext.class);
return new ResourceConfig(SampleResource.class).property("contextConfig", mockContext);
}
The fail message is:
2016-05-13 13:25:39.617 WARN 9832 --- [ main] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myRepositoryImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.jdbc.core.JdbcTemplate com.repository.impl.myRepositoryImpl.jdbcTemplate; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$JdbcTemplateConfiguration': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private javax.sql.DataSource org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$JdbcTemplateConfiguration.dataSource; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration$NonEmbeddedConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.sql.DataSource]: Factory method 'dataSource' threw exception; nested exception is org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Cannot determine embedded database driver class for database type NONE. If you want an embedded database please put a supported one on the classpath. If you have database settings to be loaded from a particular profile you may need to active it (no profiles are currently active).
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.422 sec <<< FAILURE! - in com.ws.server.SampleResourceTest
testSampleGetWithCorrectParameters(com.ws.server.SampleResourceTest) Time elapsed: 0.015 sec <<< ERROR!
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myRepositoryImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.jdbc.core.JdbcTemplate com.repository.impl.MyRepositoryImpl.jdbcTemplate; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$JdbcTemplateConfiguration': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private javax.sql.DataSource org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$JdbcTemplateConfiguration.dataSource; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration$NonEmbeddedConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.sql.DataSource]: Factory method 'dataSource' threw exception; nested exception is org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Cannot determine embedded database driver class for database type NONE. If you want an embedded database please put a supported one on the classpath. If you have database settings to be loaded from a particular profile you may need to active it (no profiles are currently active).
at org.springframework.boot.autoconfigure.jdbc.DataSourceProperties.getDriverClassName(DataSourceProperties.java:180)
at org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$NonEmbeddedConfiguration.dataSource(DataSourceAutoConfiguration.java:121)
How to use the SpringBoot context for this jersey test?

SImply put, you can't use both Spring's TestContext and Jersey Test Framework together. They will operate on two different ApplicationContexts. Even if you try to inject the ApplicationContext (created be the TestContext) into the test class and pass it to the ResourceConfig in the configure method, it's too late, as the injection doesn't occur until after construction, but the `configure method is called during contruction.
Forget JerseyTest and just use #WebIntegrationTest. See the sample from the spring boot project.
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(SampleJerseyApplication.class)
#WebIntegrationTest(randomPort = true)
public class SampleJerseyApplicationTests {
#Value("${local.server.port}")
private int port;
In a Jersey/Boot environment, Jersey needs to run in a web app environment, and that's what the #WebIntegrationTest does.
For the client, instead of just calling target on the JerseyTest, you will just need to create the client
Client client = ClientBuilder.newClient();
WebTarget target = client.target("http://localhost:" + this.port);
Response response = target.path("/sampleresource/samplepath/" + id).request().get();

Related

Error creating bean; Unsatisfied dependency expressed through field

I have a central library for certain functions and now I have trouble integrating that library.
The library is written in spring boot and contains a class: com.common.Security.
It is defined like this:
package com.common;
....
#Service
#EnableConfigurationProperties(SecurityProperties.class)
#Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class Security {
....
}
I try to use this in another class:
package org.special;
import com.common.Security;
#Configuration
public class WebServiceConfig {
#Autowired
private Security security;
....
}
But I get some errors:
Error creating bean with name 'myController': Unsatisfied dependency expressed through field 'WebServiceclient';
nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'webserviceClient':
Unsatisfied dependency expressed through field 'template'; nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'webServiceTemplate' defined in class path resource [org/special/WebServiceConfig.class]:
Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException:
Failed to instantiate [org.springframework.ws.client.core.WebServiceTemplate]: Factory method 'webServiceTemplate' threw exception;
nested exception is org.springframework.beans.factory.BeanCreationException:
nested exception is org.springframework.beans.factory.support.ScopeNotActiveException: Error creating bean with name 'scopedTarget.Security': Scope 'request' is not active for the current thread;
consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found:
What can I do to fix this?
Removing the Scope was quite helpfull.
I tried this before but some of my tests failed after that. I didn't see, that this was because of missing settings in application.yaml for the tests.
They were not neccessary when scope is request.

Spring Boot 1.5.2 - Cannot find Bean due to " Cannot search for matching files underneath URL "?

I'm using Spring Boot 1.5.2 and it has this annoying error which I could not understand the reason.
I have a Main class with these scanning configured:
#EnableJpaRepositories(basePackages = {"com.abc", "org.abc"})
#EntityScan(basePackages = {"com.abc", "org.abc", "abc"})
#ComponentScan(basePackages = {"com.abc", "org.abc", "abc"})
public class ApplicationMain extends SpringBootServletInitializer {
....
}
A model class
File: AbcUser.java
package com.abc.admin.model
#Entity
#Table(name = AbcUser.TABLE_NAME)
public class AbcUser {
}
And an interface class which extends CrudRepository:
File UserRespository.java inside this package.
package com.abc.repository.interfaces
#Repository
public interface UserRespository extends CrudRepository<AbcUser, Long> {
#Transactional
Long deleteByUsername(String username);
}
Now, when I tried to start the web application, it first has the warning which says, it cannot scand files...And then throws error, that the Bean cannot be found.
java -jar abc.war
WARN: Cannot search for matching files underneath URL [war:file:/home//tmp/build/applications/petascope/petascope_main/target/abc.war*/WEB-INF/classes/org/abc/] because it does not correspond to a directory in the file system
java.io.FileNotFoundException: URL [war:file:/home//tmp/build/applications/petascope/petascope_main/target/abc.war*/WEB-INF/classes/org/abc/] cannot be resolved to absolute file path because it does not reside in the file system: war:file:/home//tmp/build/applications/petascope/petascope_main/target/abc.war*/WEB-INF/classes/org/abc/
at org.springframework.util.ResourceUtils.getFile(ResourceUtils.java:218)
at org.springframework.core.io.AbstractFileResolvingResource.getFile(AbstractFileResolvingResource.java:52)
at org.springframework.core.io.UrlResource.getFile(UrlResource.java:213)
at org.springframework.core.io.support.PathMatchingResourcePatternResolver.doFindPathMatchingFileResources(PathMatchingResourcePatternResolver.java:685)
at org.springframework.core.io.support.PathMatchingResourcePatternResolver.findPathMatchingResources(PathMatchingResourcePatternResolver.java:477)
at org.springframework.core.io.support.PathMatchingResourcePatternResolver.getResources(PathMatchingResourcePatternResolver.java:279)
at org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager.buildDefaultPersistenceUnitInfo(DefaultPersistenceUnitManager.java:525)
at org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager.readPersistenceUnitInfos(DefaultPersistenceUnitManager.java:505)
at org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager.preparePersistenceUnitInfos(DefaultPersistenceUnitManager.java:442)
at org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager.afterPropertiesSet(DefaultPersistenceUnitManager.java:426)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:325)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:370)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:359)
at org.abc.MigrationBeanApplicationConfiguration.createEntityManagerFactory(MigrationBeanApplicationConfiguration.java:313)
Due to it cannot create Bean
ERROR [2021-08-23 16:32:17] TomcatStarter#63: Error starting Tomcat context. Exception: org.springframework.beans.factory.UnsatisfiedDependencyException. Message: Error creating bean with name 'requestsFilter': Unsatisfied dependency expressed through field 'userRepositoryService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userRepositoryService': Unsatisfied dependency expressed through field 'userRepository'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userRespository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not a managed type: class com.rasdaman.admin.model.RasdamanUser
WARN [2021-08-23 16:32:17] AnnotationConfigEmbeddedWebApplicationContext#550: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.boot.context.embedded.EmbeddedServletContainerException: Unable to start embedded Tomcat
ERROR [2021-08-23 16:32:17] SpringApplication#815: Application startup failed
org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.boot.context.embedded.EmbeddedServletContainerException: Unable to start embedded Tomcat
...
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userRespository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not a managed type: class com.abc.admin.model.AbcUser
I found the solution for the scanning problem which leads to the error of Bean not found from https://shekerama.wordpress.com/2017/03/25/how-to-solve-java-lang-illegalargumentexception-not-an-managed-type/.
final LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
entityManagerFactory.setPackagesToScan("com.abc", "org.abc");

Mock a method bean to avoid NullPointerException

I have a method bean that reads a file and returns a NullPointerException when the file doesn't exist. When I am running tests, I don't expect that file to exist so I want to mock that method bean to return a dummy response. It doesn't seem to be working however, and I'm getting an error like this:
"class":"o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext"
,"rest":"Exception encountered during context initialization -
cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'someName' defined in class path resource
[../../Someconfiguration.class]: Bean instantiation via factory method failed;
nested exception is org.springframework.beans.BeanInstantiationException:
Failed to instantiate [className]: Factory method 'someName' threw exception;
nested exception is java.lang.NullPointerException"}
The method looks like this:
#Bean
#Qualifier(SOME_QUALIFIER)
public className someName() {
// read file and return null exception if it doesn't exist
}
Would appreciate any ideas on fixing this.
This seems like a use case for Spring profiles.
Mark this method with a positive profile that is only active in production, or a negative profile that is only active in test:
#Bean #Profile("production")
#Qualifier(SOME_QUALIFIER)
public className someName() {
or
#Bean #Profile("!test")
#Qualifier(SOME_QUALIFIER)
public className someName() {
of course you will have to substitute a test configuration that is active for the test profile.

Can't run test on spring boot application because of injection of persistence dependencies failed

I have my java spring boot application and I'd like to write some tests using mockmvc; so this is the testing class:
#RunWith(SpringRunner.class)
#WebMvcTest(controllers = {IndexController.class})
#ComponentScan(basePackages={"com.sherlock.discoteque"})
#EnableJpaRepositories("com.sherlock.discoteque.repository")
#EntityScan(basePackages={"com.sherlock.discoteque"})
public class DiscotequeApplicationTests {
private MockMvc mockMvc;
#Autowired
private WebApplicationContext webApplicationContext;
#Before
public void setup() {
this.mockMvc = MockMvcBuilders.standaloneSetup(webApplicationContext).build();
}
#Test
public void testAlbumInfo() throws Exception{
this.mockMvc.perform(get("/")).andExpect(status().isOk());
}
}
but when I execute the code I have the following error message:
Field albumRepository in com.sherlock.discoteque.controller.AlbumController required a bean of type 'javax.persistence.EntityManagerFactory' that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type
'javax.persistence.EntityManagerFactory' in your configuration.
...
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'albumController': Unsatisfied
dependency expressed through field 'albumRepository'; nested exception
is org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'albumRepositoryImpl': Injection of
persistence dependencies failed; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type 'javax.persistence.EntityManagerFactory'
available
Caused by: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'albumRepositoryImpl': Injection of
persistence dependencies failed; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type 'javax.persistence.EntityManagerFactory'
available
Which is weird, considering the fact that without the testing class everything works fine. This is the class AlbumRepositoryImpl
public class AlbumRepositoryImpl implements AlbumRepositoryCustom {
private final static String RECENT_ALBUMS_QUERY = "select * from album order by createdate desc limit ?";
#PersistenceContext
public EntityManager entityManager;
#Override
public List<Album> getRecentAlbums(int size) {
if(size<1){
throw new IllegalArgumentException();
}
Query query = entityManager.createNativeQuery(RECENT_ALBUMS_QUERY, Album.class);
query.setParameter(1, size);
return query.getResultList();
}
}
and inside the AlbumController I do have the attribute
#Autowired
private AlbumRepository albumRepository;
and I have the AlbumRepository interface as well (extended from JpaRepository). I really don't know what to do to make the web application running on test, could anybody help me?
In sample code , you are trying to autowire the context , however you have not provided the test configuration.
In your project you have defined JPA entity manager configuration , but in test file you are not providing that info. Spring won't be able to start the container till you don't provide the necessary configuration in test class.
You can take an idea from https://www.petrikainulainen.net/programming/spring-framework/integration-testing-of-spring-mvc-applications-configuration/
Try to set spring boot profile with annotation - #ActiveProfiles("you_profile")

Failed to determine a suitable driver class

when starting the application, see the below error:
Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'blockDataController': Injection of resource dependencies failed;
nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'blockSummaryImpl': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'prodCodeMapper' defined in file [D:\YueNiuProject\StockMarket\yueniu-stock-data\market-data-dao\target\classes\com\yueniu\stock\market\data\mapper\block\ProdCodeMapper.class]: Unsatisfied dependency expressed through bean property 'sqlSessionFactory';
nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'sqlSessionFactory' defined in class path resource [org/mybatis/spring/boot/autoconfigure/MybatisAutoConfiguration.class]: Unsatisfied dependency expressed through method 'sqlSessionFactory' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception;
nested exception is org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Failed to determine a suitable driver class
the connection with a sql database, you must configure datasource in application.properties
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://..
spring.datasource.username=//..
spring.datasource.password=//..
if you dont need to config the datasource, you can use the exclude . like this:
#SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
it would not register the DataSource with default configuration, then passed the issue for throw Exception
sometimes if you bean configuration in same package it won't work. Like the properties loading bean need to be in separate package. Not sure this answer will be accepted or not , for me it worked after moving below code into different package.
#Bean
public PlatformTransactionManager oracleTransactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(oracleEntityManager().getObject());
return transactionManager;
}

Categories

Resources