I'd like to use Spring profile groups in fast ContextConfiguration unit tests.
Given the following application.yaml definition in test scope and profile configuration classes:
spring:
profiles:
default: test-default
group:
h2:
- test-default
- database
- h2
and configuration classes like
#Configuration
#EnableJpaRepositories(basePackageClasses = [OrderRepository::class] )
#EnableTransactionManagement
#EntityScan( basePackageClasses = [ OrderEntity::class])
#Profile("database")
class DatabaseConfiguration {}
I'd like to write a fast test with (#ContextConfiguration) e.g.
#ActiveProfiles("h2", "database", "test-default")
#ContextConfiguration( classes = [TestDefaultConfiguration::class])
internal class DbIngestionEventHandlerIntegrationTest()
I have to define both, h2 and database profiles, because ContextConfiguration does not load the application.yaml.
Is it possible to define spring profile groups programmatically? - so that they can be reused in tests?
Switching from spring boot back to "normal" spring because the app only uses some jdbc code to "upsert" into a postgresql database.
1)
tried annotating the test class with:
#RunWith(SpringJUnit4ClassRunner.class)
public class DBIntegration {
results in:
java.lang.IllegalStateException: Failed to load ApplicationContext
2)
tried annotating the class with:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {})
public class DBIntegration {
[main] INFO org.springframework.test.context.support.AbstractContextLoader - Could not detect default resource locations for test class [de.mydomain.myproject.DBIntegration]: no resource found for suffixes {-context.xml}.
No exceptions, but java.lang.Exception: No tests found matching [{ExactMatcher:fDisplayName=insertDataFrom_sometest],
3) tried annotating the class with:
#Component
public class DBIntegration {
dependency injection does not work in this case, the expected service
(to be injected) throws a nullpointerexception
I am doing unit test for my Spring Boot application with Camel. When the application runs, it can get bean which is configured as a #Component
#Component("agencyExporterProcessor")
public class AgencyExporterProcessor {}
and I get the bean like this :
from(getTriggerExportEndpoint())
.routeId(getTriggerExportId())
// When shutting down, Camel will wait until the batch completed
.shutdownRunningTask(ShutdownRunningTask.CompleteAllTasks)
.log("[SamCustomExporter] - RouteId:${routeId} - Begin at ${date:now:MM/dd/yyyy HH:mm:ss.SSS}")
.setHeader(Messaging.Names.SAM_DATA_AGENCY_CONFIGURATION_HEADER_KEY.toString(), constant(getConfiguration()))
// Initialize a list to store exported CSV file names
.bean(agencyExporterProcessor, "prepareExportedFileList")
But when I test, the route cannot get the bean"
org.apache.camel.FailedToCreateRouteException: Failed to create route agencyExporterRoute_triggerExport at: >>> Bean[ref:agencyExporterProcessor method:prepareExportedFileList] <<< in route: Route(agencyExporterRoute_triggerExport)[[From[direct:agency... because of No bean could be found in the registry for: agencyExporterProcessor
This is how I configured my unit test class:
#DirtiesContext
#RunWith(SpringRunner.class)
#EnableAutoConfiguration
#SpringBootApplication
#SpringBootTest(classes = SamCustomExporterSpringApplication.class,
webEnvironment = SpringBootTest.WebEnvironment.NONE)
public class AgencyExporterRouteTest extends BaseRouteTestSupport {}
Please give advice!!!! Many thanks
You should refer to the bean name as a String value in the Camel route:
.bean("agencyExporterProcessor", "prepareExportedFileList")
Using gradle (3.4.1) with an integrationTest configuration, the tests using the ConfigurationProperties of Spring Boot (1.5.1.RELEASE) is failing to initialize even though the application initializes correctly (./gradlew bootRun). The class annotated with ConfigurationProperties is similar to the following
#Component
#ConfigurationProperties(prefix = "foo")
#Validated
public class AppConfiguration {
#NonNull
private URL serviceUrl;
...
The configuration file does have getters and setters. The error that is generated is similar to the following
java.lang.IllegalStateException: Failed to load ApplicationContext
....
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'AppConfiguration': Could not bind properties to AppConfiguration
....
Caused by: org.springframework.validation.BindException: org.springframework.boot.bind.RelaxedDataBinder$RelaxedBeanPropertyBindingResult
Field error in object 'foo' on field 'serviceUrl': rejected value [null]; codes ...
The configuration class of the integration test is annotated as follows
#Configuration
#ComponentScan(...)
#EnableConfigurationProperties
#EnableIntegration
public static class ContextConfiguration {}
The test class had the following annotations
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration
public class ReleaseTest {
...
After looking at the Spring Boot code for the ConfigurationPropertiesBindingPostProcessor#postProcessBeforeInitialization() it suggested that the property source was not being discovered. Adding the org.springframework.boot:spring-boot-starter-test artifact as a compile-time dependency and modifying the context configuration of the test class to
#ContextConfiguration(initializers = ConfigFileApplicationContextInitializer.class)
the AppConfiguration class was initialized properly using a YAML-based properties file.
An alternative is to add
#TestPropertySource("classpath:/application.properties")
This approach doesn't require the spring-boot-starter-test dependency and requires that a "traditional" properties file is used (a YAML file will not work with this approach).
I have the following test class:
#ActiveProfiles({ "DataTC", "test" })
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {BaseTestConfiguration.class, DataTestConfiguration.class, JpaConfiguration.class, PropertyPlaceholderConfiguration.class })
public class RegularDayToTimeSlotsTest {
...
The issue seems to come from the BaseTestConfiguration class:
#Configuration
#ComponentScan(basePackages = { "com.bignibou" }, excludeFilters = { #Filter(type = FilterType.CUSTOM, value = RooRegexFilter.class),
#Filter(type = FilterType.ANNOTATION, value = Controller.class), #Filter(type = FilterType.ANNOTATION, value = ControllerAdvice.class) })
public class BaseTestConfiguration {
}
I systematically get this exception:
Caused by: java.lang.IllegalArgumentException: A ServletContext is required to configure default servlet handling
at org.springframework.util.Assert.notNull(Assert.java:112)
at org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer.<init>(DefaultServletHandlerConfigurer.java:54)
at org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport.defaultServletHandlerMapping(WebMvcConfigurationSupport.java:329)
at org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration$$EnhancerByCGLIB$$bb4ceb44.CGLIB$defaultServletHandlerMapping$22(<generated>)
at org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration$$EnhancerByCGLIB$$bb4ceb44$$FastClassByCGLIB$$368bb5c1.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:326)
at org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration$$EnhancerByCGLIB$$bb4ceb44.defaultServletHandlerMapping(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:166)
... 43 more
I am not sure how to get around this issue. Somehow Spring is looking for a ServletContext when I run the test and I get the above exception...
One of your #Configuration classes is obviously annotated with #EnableWebMvc. That's how DelegatingWebMvcConfiguration ends up in your stack trace, since it is imported by #EnableWebMvc.
So although you think you don't need a WebApplicationContext (and hence a ServletContext), you in fact do need it simply because you are loading an application context with #EnableWebMvc.
You have two options:
Compose the configuration classes for your integration test so that you are not including the web-related configuration (i.e., the #Configuration class(es) annotated with #EnableWebMvc).
Annotate your test class with #WebAppConfiguration as suggested in other comments above.
Regards,
Sam (author of the Spring TestContext Framework)
It seems like you are missing
#WebAppConfiguration
from your test class.
The documentation states
The resource base path is used behind the scenes to create a
MockServletContext which serves as the ServletContext for the test’s
WebApplicationContext.
Typically a Servlet container would provide the ServletContext. Since you are in a testing environment, you need a fake. #WebAppConfiguration provides that.
For you to instantiate the Servlet context, you would have to use the annotation.
#WebAppConfiguration
A class-level annotation that is used to declare that the ApplicationContext loaded for an integration test should be a WebApplicationContext. The mere presence of #WebAppConfiguration on a test class ensures that a WebApplicationContext will be loaded for the test, using the default value of "file:src/main/webapp" for the path to the root of the web application (i.e., the resource base path). The resource base path is used behind the scenes to create a MockServletContext which serves as the ServletContext for the test’s WebApplicationContext.
I was getting a similar error but whilst running the application normally rather than trying to run tests.
It turns out if you're making use of a custom PermissionEvaluator then you need to declare it in a separate #Configuration class to the one with your main Spring security configuration in.
See: How do I add method based security to a Spring Boot project?
There is also an open Github issue: https://github.com/spring-projects/spring-boot/issues/4875