I am using Spring Boot 1.4, Spock and spring-boot-starter-security. Here is my relevant gradle file:
springBootVersion = '1.4.0.BUILD-SNAPSHOT'
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
compile('org.springframework.boot:spring-boot-starter-data-jpa')
compile('org.springframework.boot:spring-boot-devtools')
compile('org.springframework.boot:spring-boot-starter-security')
compile('org.springframework.boot:spring-boot-starter-web')
compile('org.jasypt:jasypt-spring31:1.9.2')
compile('org.apache.httpcomponents:httpclient:4.5.2')
testCompile('org.springframework.boot:spring-boot-starter-test')
testCompile('org.spockframework:spock-core:1.1-groovy-2.4-rc-2')
testCompile('org.spockframework:spock-spring:1.1-groovy-2.4-rc-2')
I also have added this to my application-test.properties file:
server.ssl.enabled=false
spring.datasource.username=test
spring.datasource.password=test
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
I was able to create an authenticated endpoint that creates a JWT (using jasypt-spring31:1.9.2) and returns it in the Authorization header. This works great when accessing via browser or Postman. However, I have not been able to make this work in my Spring Boot Integration Test.
I do have the DB Configuration class since my password is encrypted:
@Configuration
public class DBConfig {
@Autowired
private Environment env;
@Value("${spring.datasource.driverClassName}")
private String databaseDriverClassName;
@Value("${spring.datasource.url}")
private String datasourceUrl;
@Value("${spring.datasource.username}")
private String databaseUsername;
@Value("${jasypt.key}")
private String jasyptKey;
@Bean
public DataSource datasource() throws IOException {
return DataSourceBuilder
.create()
.username(databaseUsername)
.password(getSecurePassword())
.url(datasourceUrl)
.driverClassName(databaseDriverClassName)
.build();
}
private String getSecurePassword() throws IOException {
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
encryptor.setPassword(jasyptKey);
Properties props = new EncryptableProperties(encryptor);
props.load(this.getClass().getClassLoader().getResourceAsStream("application-" + env.getActiveProfiles()[0] + ".properties"));
return props.getProperty("spring.datasource.password");
}
}
My base test class will start up an embedded Tomcat instance and make all endpoints available, and has a method to get the JWT:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@TestPropertySource("classpath:application-test.properties")
class BaseSpecification extends Specification {
@Autowired
def TestRestTemplate restTemplate
String loginAndGetJWT() {
def model = new ModelMap();
model.addAttribute("username", "ausername")
model.addAttribute("password", "apassword");
ResponseEntity<JwtAuthenticationResponse> response = restTemplate.getForEntity("/auth", String.class, model);
def jwt = response.getBody().token
return jwt;
}
}
When I try to run my sample test:
class ApplicationSpecWithoutAnnotation extends BaseSpecification {
@Autowired
WebApplicationContext context
def "should boot up without errors"() {
expect: "web application context exists"
context != null
}
}
I get the following:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testRestTemplate': Initialization of bean failed; nested exception is java.lang.NoClassDefFoundError: Could not initialize class org.apache.http.conn.ssl.SSLConnectionSocketFactory
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) ~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
According to this: TestRestTemplate is now available as bean whenever @SpringBootTest is used.
If I remove compile('org.apache.httpcomponents:httpclient:4.5.2') then the error changes to:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testRestTemplate': Initialization of bean failed; nested exception is java.lang.NoClassDefFoundError: org/apache/http/impl/client/HttpClients
So there appears to be a dependency on Spring web & apache that doesn't seem right.