Spring Boot 2.1 - #WebMvcTest without Spring Security Auto-Configuration - spring-boot

Before migrating to Spring Boot 2.1, we had a couple of controller tests in our services utilizing #WebMvcTest in combination with #AutoConfigureMockMvc:
#WebMvcTest(SomeController.class)
#AutoConfigureMockMvc(secure = false)
public class SomeControllerTests { ... }
This had the effect that the Spring Security configuration was disabled and you could run MVC tests without mocking OAuth/JWT.
In Spring Boot 2.1, the secured attribute is deprecated and the release notes mention that
[...] #WebMvcTest looks for a WebSecurityConfigurer bean [...].
In order to avoid the deprecated secured attribute and loading of our WebSecurityConfigurer we rewrote our tests to:
#WebMvcTest(
value = SomeController.class,
excludeFilters = #ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = WebSecurityConfigurer.class),
excludeAutoConfiguration = MockMvcSecurityAutoConfiguration.class)
public class SomeControllerTests { ... }
The question is: is there a more compact way in Spring Boot 2.1 to define such tests?

Yes, rather than working around the fact the flag is deprecated, you should embrace the fact that this is going in that direction going forward.
As of Spring Boot 2.1, if you have Spring Security, your tests will be secured using your custom configuration. What is the actual problem with that?
If you don't want to authenticate for certain tests, just use Spring Security's test infrastructure and add #WithMockUser.

Encountered the same scenario and what helped was using the below annotations instead of #WebMvcTest. In this case, #WithMockUser did not help.
#WebAppConfiguration
#Import({MockMvcAutoConfiguration.class})
#EnableConfigurationProperties({ResourceProperties.class, WebMvcProperties.class})
Classes that existed in controllers / value of #WebMvcTest goes into value of #Import annotation.
Source: https://github.com/spring-projects/spring-boot/issues/14227#issuecomment-688824627

Related

Springboot 2 controller integration test transactional (lazy-loading) session issue

Issue
I had an Hibernate lazy loading issue when using Postman to send a reqeust derectly to a Springboot service endpoint, which is bacause I have a collection marked as FetchType.Lazy in an entity and this issue can be resolved by marking the service method as #Transactional.
However, if I remove that #Transactional, my Springboot controller test still passed without any Hibernate lazy loading issue.
This looks like all of the Springboot controller integration tests are always transactional. But I couldn't find any official document about it. So, my question is, is it correct?
For my integration test, I use the annotations below
#RunWith(SpringRunner.class)
#SpringBootTest(classes = ApiApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#TestPropertySource(locations = "classpath:application.properties")
As #Josef said in comment above, my issue here is about default Spring jpa config spring.jpa.oepn-in-view=true. For more details, please read:
What is this spring.jpa.open-in-view=true property in Spring Boot?
https://www.baeldung.com/spring-open-session-in-view

Upgrading from Java Config to Spring Boot

Upgrading an existing system to Spring Boot with Auto config. Currently the system is all Java config. I'm confused over whether to continue the use of #Profile. Is this annotation no longer needed? I searched extensively about upgrading and found only references to non-Spring Java migration and creating new projects.
Typical #Profile usage in our configuration classes looks something like:
#Bean
#Profile("is-standalone")
public Service unsecuredService(SomeApi someApi) {
return new ...
}
I inferred from the Spring Boot examples that using one of the #Conditional annotations is recommended like this:
#Bean
#ConditionalOnProperty("unsecured.enabled")
public Service unsecuredService(SomeApi someApi) {
return new ...
}
Then in a YAML file the is-standalone Profile enables or disables all the various properties for that Profile. Is this the proper way to upgrade? To repeat a question from above differently, can the #Profile usage be left as is? This is for a fairly large project, the upgrade is non-trivial, so I would like to do this only once!
Depends where your previous #Profile annotation is coming from. If you're using Spring's #Profile, the functionality is as follows:
Annotating a class with #Profile("dev") will load the class and register it in the Spring context only when the dev profile is active
Annotating a class with #Profile("!dev") will load the class and register it in the Spring context only when the dev profile is inactive
If this sounds like what you have already, no change is needed.

Disable autoconfiguration for Spring Cloud Config in a test class of a Spring Boot application

I have a test class annotated with #DataJpaTest which autoconfigures Cloud Config.
I want to stop that for that one test class. I cannot use the spring.cloud.config.enabled=false application property, because that would disable it for all tests.
Any suggestions?
#DataJpaTest annotation has other attributes. I tried the following to specifically disable the Spring Cloud Config and it worked for me locally:
#DataJpaTest(properties = {"spring.cloud.config.enabled=false"})
#DataJpaTest takes a excludeAutoConfiguration argument. You can specify all the AutoConfig's which you want to exclude.
#DataJpaTest(excludeAutoConfiguration = {AbcCloudAutoConfig.class, DefCloudAutoConfig.class})
replace AbcCloudAutoConfig, DefCloudAutoConfig with the classes you want to exclude

Spring-Boot module based integration testing

I have a multi-module Spring-Boot project.
I was wondering how I can set up integration testing just to test Spring Data JPA repositories? The following approach fails with this exception:
HV000183: Unable to load 'javax.el.ExpressionFactory'. Check that you have the EL dependencies on the classpath.
Since this module does not depend on the web module, there is no web application that can be started.
#RunWith(SpringJUnit4ClassRunner.class)
#IntegrationTest
#SpringApplicationConfiguration(classes = TestConfiguration.class)
class CardInfoRepositoryIT {
#Autowired CardInfoRepository cardInfoRepository;
#Test
void testLoadData() {
assert cardInfoRepository.findAll().size() == 1
}
}
As Marten mentioned, #IntegrationTest should only be used when you need to test against the deployed Spring Boot application (e.g., deployed in an embedded Tomcat, Jetty, or Undertow container). So if your goal is to test your repository layer in isolation, you should not use #IntegrationTest.
On the other hand, if your tests require specific Spring Boot functionality (in contrast to standard Spring Framework functionality, semantics, and defaults), then you will in fact want to annotate your test class with #SpringApplicationConfiguration instead of #ContextConfiguration. The reason is that #SpringApplicationConfiguration preconfigures the SpringApplicationContextLoader which is specific to Spring Boot.
Furthermore, if you want your repository layer integration tests to run faster (i.e., without the full overhead of Spring Boot), you may choose to exclude configuration classes annotated with #EnableAutoConfiguration since that will auto-configure every candidate for auto-configuration found in the classpath. So, for example, if you just want to have Spring Boot auto-configure an embedded database and Spring Data JPA (with Hibernate as the JPA provider) along with entity scanning, you could compose your test configuration something like this:
#Configuration
#EnableJpaRepositories(basePackageClasses = UserRepository.class)
#EntityScan(basePackageClasses = User.class)
#Import({ DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class })
public class TestRepositoryConfig {}
And then use that configuration in your test class like this:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = TestRepositoryConfig.class)
#Transactional
public class UserRepositoryTests { /* ... */ }
Regards,
Sam
p.s. You might find my answer to the following, related question useful as well: Disable security for unit tests with spring boot
I resolved this by having the following test config class.
#Configuration
#EnableAutoConfiguration
#ComponentScan
#PropertySource("classpath:core.properties")
class TestConfiguration {
}
core.properties is also used by the main application and it contains datasource information. #IntegrationTest annotation can be removed on the test class.
I also added the following to the module as dependencies:
testRuntime 'javax.el:javax.el-api:2.2.4'
testRuntime 'org.glassfish.web:javax.el:2.2.4'

How to disable Spring Boot's autoconfiguration for Apache Velocity?

I'm experimenting with Spring Boot (1.1.9.RELEASE) and Apache Velocity (1.7) with the intention of using Velocity as a templating tool for generating emails. I'm using Thymeleaf (2.1.3.RELEASE) for web templates.
Spring Boot's Autoconfiguration detects Velocity on the classpath during start up and adds it as a web view resolver. While this is brilliant, it's not what I want so I tried
#EnableAutoConfiguration(exclude = {VelocityAutoConfiguration.class})
public class Application {
but I still ended up with a velocityViewResolver bean once the application had started up.
Any idea how I might go about disabling this automatic configuration?
Thanks in advance for any replies.
With Spring Boot 1.2.5, disabling the autoconfiguration on the main application class seems to be enough:
#SpringBootApplication
#EnableAutoConfiguration(exclude = { VelocityAutoConfiguration.class })
Edit
I don't exactly know since when that works, but now (Spring Boot 1.3.2) you can also set :
spring.velocity.enabled=false
in application.properties.

Resources