Decorate test containers so tests are skipped without Docker
Closes gh-15901 Closes gh-15638
This commit is contained in:
parent
46bf82ca82
commit
9fb0b97f96
|
|
@ -28,6 +28,7 @@ import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
|
||||||
import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration;
|
import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.data.cassandra.city.City;
|
import org.springframework.boot.autoconfigure.data.cassandra.city.City;
|
||||||
import org.springframework.boot.test.util.TestPropertyValues;
|
import org.springframework.boot.test.util.TestPropertyValues;
|
||||||
|
import org.springframework.boot.testsupport.testcontainers.SkippableContainer;
|
||||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||||
import org.springframework.data.cassandra.config.CassandraSessionFactoryBean;
|
import org.springframework.data.cassandra.config.CassandraSessionFactoryBean;
|
||||||
import org.springframework.data.cassandra.config.SchemaAction;
|
import org.springframework.data.cassandra.config.SchemaAction;
|
||||||
|
|
@ -43,7 +44,8 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
public class CassandraDataAutoConfigurationIntegrationTests {
|
public class CassandraDataAutoConfigurationIntegrationTests {
|
||||||
|
|
||||||
@ClassRule
|
@ClassRule
|
||||||
public static CassandraContainer<?> cassandra = new CassandraContainer<>();
|
public static SkippableContainer<CassandraContainer<?>> cassandra = new SkippableContainer<>(
|
||||||
|
CassandraContainer::new);
|
||||||
|
|
||||||
private AnnotationConfigApplicationContext context;
|
private AnnotationConfigApplicationContext context;
|
||||||
|
|
||||||
|
|
@ -51,7 +53,8 @@ public class CassandraDataAutoConfigurationIntegrationTests {
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
this.context = new AnnotationConfigApplicationContext();
|
this.context = new AnnotationConfigApplicationContext();
|
||||||
TestPropertyValues
|
TestPropertyValues
|
||||||
.of("spring.data.cassandra.port=" + cassandra.getFirstMappedPort(),
|
.of("spring.data.cassandra.port="
|
||||||
|
+ cassandra.getContainer().getFirstMappedPort(),
|
||||||
"spring.data.cassandra.read-timeout=24000",
|
"spring.data.cassandra.read-timeout=24000",
|
||||||
"spring.data.cassandra.connect-timeout=10000")
|
"spring.data.cassandra.connect-timeout=10000")
|
||||||
.applyTo(this.context.getEnvironment());
|
.applyTo(this.context.getEnvironment());
|
||||||
|
|
@ -96,7 +99,8 @@ public class CassandraDataAutoConfigurationIntegrationTests {
|
||||||
|
|
||||||
private void createTestKeyspaceIfNotExists() {
|
private void createTestKeyspaceIfNotExists() {
|
||||||
Cluster cluster = Cluster.builder().withoutJMXReporting()
|
Cluster cluster = Cluster.builder().withoutJMXReporting()
|
||||||
.withPort(cassandra.getFirstMappedPort()).addContactPoint("localhost")
|
.withPort(cassandra.getContainer().getFirstMappedPort())
|
||||||
|
.addContactPoint(cassandra.getContainer().getContainerIpAddress())
|
||||||
.build();
|
.build();
|
||||||
try (Session session = cluster.connect()) {
|
try (Session session = cluster.connect()) {
|
||||||
session.execute("CREATE KEYSPACE IF NOT EXISTS boot_test"
|
session.execute("CREATE KEYSPACE IF NOT EXISTS boot_test"
|
||||||
|
|
|
||||||
|
|
@ -18,13 +18,17 @@ package org.springframework.boot.test.autoconfigure.data.neo4j;
|
||||||
|
|
||||||
import org.junit.ClassRule;
|
import org.junit.ClassRule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.junit.rules.TestRule;
|
||||||
|
import org.junit.runner.Description;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
import org.junit.runners.model.Statement;
|
||||||
import org.neo4j.ogm.session.Session;
|
import org.neo4j.ogm.session.Session;
|
||||||
import org.testcontainers.containers.Neo4jContainer;
|
import org.testcontainers.containers.Neo4jContainer;
|
||||||
|
|
||||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.util.TestPropertyValues;
|
import org.springframework.boot.test.util.TestPropertyValues;
|
||||||
|
import org.springframework.boot.testsupport.testcontainers.SkippableContainer;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.ApplicationContextInitializer;
|
import org.springframework.context.ApplicationContextInitializer;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
|
@ -46,9 +50,18 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||||
@DataNeo4jTest
|
@DataNeo4jTest
|
||||||
public class DataNeo4jTestIntegrationTests {
|
public class DataNeo4jTestIntegrationTests {
|
||||||
|
|
||||||
|
public static SkippableContainer<Neo4jContainer<?>> neo4j = new SkippableContainer<Neo4jContainer<?>>(
|
||||||
|
() -> new Neo4jContainer<>().withAdminPassword(null));
|
||||||
|
|
||||||
@ClassRule
|
@ClassRule
|
||||||
public static Neo4jContainer<?> neo4j = new Neo4jContainer<>()
|
public static TestRule skippableContainer = new TestRule() {
|
||||||
.withAdminPassword(null);
|
|
||||||
|
@Override
|
||||||
|
public Statement apply(Statement base, Description description) {
|
||||||
|
return neo4j.apply(base, description);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private Session session;
|
private Session session;
|
||||||
|
|
@ -81,7 +94,8 @@ public class DataNeo4jTestIntegrationTests {
|
||||||
@Override
|
@Override
|
||||||
public void initialize(
|
public void initialize(
|
||||||
ConfigurableApplicationContext configurableApplicationContext) {
|
ConfigurableApplicationContext configurableApplicationContext) {
|
||||||
TestPropertyValues.of("spring.data.neo4j.uri=" + neo4j.getBoltUrl())
|
TestPropertyValues
|
||||||
|
.of("spring.data.neo4j.uri=" + neo4j.getContainer().getBoltUrl())
|
||||||
.applyTo(configurableApplicationContext.getEnvironment());
|
.applyTo(configurableApplicationContext.getEnvironment());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import org.testcontainers.containers.Neo4jContainer;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.util.TestPropertyValues;
|
import org.springframework.boot.test.util.TestPropertyValues;
|
||||||
|
import org.springframework.boot.testsupport.testcontainers.SkippableContainer;
|
||||||
import org.springframework.context.ApplicationContextInitializer;
|
import org.springframework.context.ApplicationContextInitializer;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
|
|
@ -43,8 +44,8 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
public class DataNeo4jTestPropertiesIntegrationTests {
|
public class DataNeo4jTestPropertiesIntegrationTests {
|
||||||
|
|
||||||
@ClassRule
|
@ClassRule
|
||||||
public static Neo4jContainer<?> neo4j = new Neo4jContainer<>()
|
public static SkippableContainer<Neo4jContainer<?>> neo4j = new SkippableContainer<Neo4jContainer<?>>(
|
||||||
.withAdminPassword(null);
|
() -> new Neo4jContainer<>().withAdminPassword(null));
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private Environment environment;
|
private Environment environment;
|
||||||
|
|
@ -60,7 +61,8 @@ public class DataNeo4jTestPropertiesIntegrationTests {
|
||||||
@Override
|
@Override
|
||||||
public void initialize(
|
public void initialize(
|
||||||
ConfigurableApplicationContext configurableApplicationContext) {
|
ConfigurableApplicationContext configurableApplicationContext) {
|
||||||
TestPropertyValues.of("spring.data.neo4j.uri=" + neo4j.getBoltUrl())
|
TestPropertyValues
|
||||||
|
.of("spring.data.neo4j.uri=" + neo4j.getContainer().getBoltUrl())
|
||||||
.applyTo(configurableApplicationContext.getEnvironment());
|
.applyTo(configurableApplicationContext.getEnvironment());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import org.testcontainers.containers.Neo4jContainer;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.util.TestPropertyValues;
|
import org.springframework.boot.test.util.TestPropertyValues;
|
||||||
|
import org.springframework.boot.testsupport.testcontainers.SkippableContainer;
|
||||||
import org.springframework.context.ApplicationContextInitializer;
|
import org.springframework.context.ApplicationContextInitializer;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.context.annotation.ComponentScan.Filter;
|
import org.springframework.context.annotation.ComponentScan.Filter;
|
||||||
|
|
@ -44,8 +45,8 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
public class DataNeo4jTestWithIncludeFilterIntegrationTests {
|
public class DataNeo4jTestWithIncludeFilterIntegrationTests {
|
||||||
|
|
||||||
@ClassRule
|
@ClassRule
|
||||||
public static Neo4jContainer<?> neo4j = new Neo4jContainer<>()
|
public static SkippableContainer<Neo4jContainer<?>> neo4j = new SkippableContainer<Neo4jContainer<?>>(
|
||||||
.withAdminPassword(null);
|
() -> new Neo4jContainer<>().withAdminPassword(null));
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ExampleService service;
|
private ExampleService service;
|
||||||
|
|
@ -61,7 +62,8 @@ public class DataNeo4jTestWithIncludeFilterIntegrationTests {
|
||||||
@Override
|
@Override
|
||||||
public void initialize(
|
public void initialize(
|
||||||
ConfigurableApplicationContext configurableApplicationContext) {
|
ConfigurableApplicationContext configurableApplicationContext) {
|
||||||
TestPropertyValues.of("spring.data.neo4j.uri=" + neo4j.getBoltUrl())
|
TestPropertyValues
|
||||||
|
.of("spring.data.neo4j.uri=" + neo4j.getContainer().getBoltUrl())
|
||||||
.applyTo(configurableApplicationContext.getEnvironment());
|
.applyTo(configurableApplicationContext.getEnvironment());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2019 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.testsupport.testcontainers;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.junit.AssumptionViolatedException;
|
||||||
|
import org.junit.rules.TestRule;
|
||||||
|
import org.junit.runner.Description;
|
||||||
|
import org.junit.runners.model.Statement;
|
||||||
|
import org.testcontainers.DockerClientFactory;
|
||||||
|
import org.testcontainers.containers.FailureDetectingExternalResource;
|
||||||
|
import org.testcontainers.containers.GenericContainer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link GenericContainer} decorator that skips test execution when Docker is not
|
||||||
|
* available.
|
||||||
|
*
|
||||||
|
* @param <T> type of the underlying container
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
*/
|
||||||
|
public class SkippableContainer<T> implements TestRule {
|
||||||
|
|
||||||
|
private final Supplier<T> containerFactory;
|
||||||
|
|
||||||
|
private T container;
|
||||||
|
|
||||||
|
public SkippableContainer(Supplier<T> containerFactory) {
|
||||||
|
this.containerFactory = containerFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Statement apply(Statement base, Description description) {
|
||||||
|
try {
|
||||||
|
DockerClientFactory.instance().client();
|
||||||
|
}
|
||||||
|
catch (Throwable ex) {
|
||||||
|
return new SkipStatement();
|
||||||
|
}
|
||||||
|
this.container = this.containerFactory.get();
|
||||||
|
return ((FailureDetectingExternalResource) this.container).apply(base,
|
||||||
|
description);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T getContainer() {
|
||||||
|
if (this.container == null) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Container cannot be accessed prior to test invocation");
|
||||||
|
}
|
||||||
|
return this.container;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SkipStatement extends Statement {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void evaluate() {
|
||||||
|
throw new AssumptionViolatedException(
|
||||||
|
"Could not find a valid Docker environment.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue