diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/spring-boot-features.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/spring-boot-features.adoc index 24a7c673f13..44e0060cb0e 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/spring-boot-features.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/spring-boot-features.adoc @@ -6947,6 +6947,34 @@ TIP: Sometimes writing Spring WebFlux tests is not enough; Spring Boot can help +[[boot-features-testing-spring-boot-applications-testing-autoconfigured-cassandra-test]] +==== Auto-configured Data Cassandra Tests +You can use `@DataCassandraTest` to test Cassandra applications. +By default, it configures a `CassandraTemplate`, scans for `@Table` classes, and configures Spring Data Cassandra repositories. +Regular `@Component` beans are not loaded into the `ApplicationContext`. +(For more about using Cassandra with Spring Boot, see "<>", earlier in this chapter.) + +TIP: A list of the auto-configuration settings that are enabled by `@DataCassandraTest` can be <>. + +The following example shows a typical setup for using Cassandra tests in Spring Boot: + +[source,java,indent=0] +---- + import org.springframework.beans.factory.annotation.Autowired; + import org.springframework.boot.test.autoconfigure.data.cassandra.DataCassandraTest; + + @DataCassandraTest + class ExampleDataCassandraTests { + + @Autowired + private YourRepository repository; + + // + } +---- + + + [[boot-features-testing-spring-boot-applications-testing-autoconfigured-jpa-test]] ==== Auto-configured Data JPA Tests You can use the `@DataJpaTest` annotation to test JPA applications. diff --git a/spring-boot-project/spring-boot-test-autoconfigure/build.gradle b/spring-boot-project/spring-boot-test-autoconfigure/build.gradle index 21f910df499..68edda9b11c 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/build.gradle +++ b/spring-boot-project/spring-boot-test-autoconfigure/build.gradle @@ -30,6 +30,7 @@ dependencies { optional("org.springframework:spring-web") optional("org.springframework:spring-webmvc") optional("org.springframework:spring-webflux") + optional("org.springframework.data:spring-data-cassandra") optional("org.springframework.data:spring-data-jdbc") optional("org.springframework.data:spring-data-jpa") optional("org.springframework.data:spring-data-ldap") @@ -78,6 +79,7 @@ dependencies { testImplementation("org.skyscreamer:jsonassert") testImplementation("org.springframework.hateoas:spring-hateoas") testImplementation("org.springframework.plugin:spring-plugin-core") + testImplementation("org.testcontainers:cassandra") testImplementation("org.testcontainers:junit-jupiter") testImplementation("org.testcontainers:neo4j") testImplementation("org.testcontainers:testcontainers") diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/data/cassandra/AutoConfigureDataCassandra.java b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/data/cassandra/AutoConfigureDataCassandra.java index cad8a2eec69..3c070088dfb 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/data/cassandra/AutoConfigureDataCassandra.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/data/cassandra/AutoConfigureDataCassandra.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -27,11 +27,11 @@ import org.springframework.boot.autoconfigure.ImportAutoConfiguration; /** * {@link ImportAutoConfiguration Auto-configuration imports} for typical Data Cassandra - * tests. Most tests should consider using {@link DataCassandraTest} rather than using - * this annotation directly. + * tests. Most tests should consider using {@link DataCassandraTest @DataCassandraTest} + * rather than using this annotation directly. * * @author Artsiom Yudovin - * @since 2.1.0 + * @since 2.4.0 * @see DataCassandraTest */ @Target(ElementType.TYPE) diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/data/cassandra/DataCassandraTest.java b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/data/cassandra/DataCassandraTest.java index 1f2f0608957..37dd6c13963 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/data/cassandra/DataCassandraTest.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/data/cassandra/DataCassandraTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -30,25 +30,25 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.test.autoconfigure.OverrideAutoConfiguration; import org.springframework.boot.test.autoconfigure.core.AutoConfigureCache; import org.springframework.boot.test.autoconfigure.filter.TypeExcludeFilters; -import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.core.annotation.AliasFor; import org.springframework.core.env.Environment; import org.springframework.test.context.BootstrapWith; import org.springframework.test.context.junit.jupiter.SpringExtension; /** - * Annotation that can be used in combination with {@code @RunWith(SpringRunner.class)} - * for a typical Cassandra test. Can be used when a test focuses only on + * Annotation that can be used for a Cassandra test that focuses only on * Cassandra components. *

* Using this annotation will disable full auto-configuration and instead apply only * configuration relevant to Cassandra tests. *

- * By default, tests annotated with {@code @DataCassandraTest} will use an embedded - * in-memory Cassandra process (if available). + * When using JUnit 4, this annotation should be used in combination with + * {@code @RunWith(SpringRunner.class)}. * * @author Artsiom Yudovin - * @since 2.1.0 + * @author Stephane Nicoll + * @since 2.4.0 */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @@ -86,14 +86,14 @@ public @interface DataCassandraTest { * application context. * @return include filters to apply */ - ComponentScan.Filter[] includeFilters() default {}; + Filter[] includeFilters() default {}; /** * A set of exclude filters which can be used to filter beans that would otherwise be * added to the application context. * @return exclude filters to apply */ - ComponentScan.Filter[] excludeFilters() default {}; + Filter[] excludeFilters() default {}; /** * Auto-configuration exclusions that should be applied for this test. diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/data/cassandra/DataCassandraTestContextBootstrapper.java b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/data/cassandra/DataCassandraTestContextBootstrapper.java index 42c33411f69..c0fc1a76c25 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/data/cassandra/DataCassandraTestContextBootstrapper.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/data/cassandra/DataCassandraTestContextBootstrapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -18,6 +18,7 @@ package org.springframework.boot.test.autoconfigure.data.cassandra; import org.springframework.boot.test.context.SpringBootTestContextBootstrapper; import org.springframework.core.annotation.MergedAnnotations; +import org.springframework.core.annotation.MergedAnnotations.SearchStrategy; import org.springframework.test.context.TestContextBootstrapper; /** @@ -25,14 +26,13 @@ import org.springframework.test.context.TestContextBootstrapper; * support. * * @author Artsiom Yudovin - * @since 2.1.0 */ -public class DataCassandraTestContextBootstrapper extends SpringBootTestContextBootstrapper { +class DataCassandraTestContextBootstrapper extends SpringBootTestContextBootstrapper { @Override protected String[] getProperties(Class testClass) { - return MergedAnnotations.from(testClass, MergedAnnotations.SearchStrategy.INHERITED_ANNOTATIONS) - .get(DataCassandraTest.class).getValue("properties", String[].class).orElse(null); + return MergedAnnotations.from(testClass, SearchStrategy.INHERITED_ANNOTATIONS).get(DataCassandraTest.class) + .getValue("properties", String[].class).orElse(null); } } diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/data/cassandra/DataCassandraTypeExcludeFilter.java b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/data/cassandra/DataCassandraTypeExcludeFilter.java index c4583067d5d..c4bae8479df 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/data/cassandra/DataCassandraTypeExcludeFilter.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/data/cassandra/DataCassandraTypeExcludeFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -23,9 +23,8 @@ import org.springframework.boot.test.autoconfigure.filter.StandardAnnotationCust * {@link TypeExcludeFilter} for {@link DataCassandraTest @DataCassandraTest}. * * @author Artsiom Yudovin - * @since 2.1.0 */ -public class DataCassandraTypeExcludeFilter extends StandardAnnotationCustomizableTypeExcludeFilter { +class DataCassandraTypeExcludeFilter extends StandardAnnotationCustomizableTypeExcludeFilter { protected DataCassandraTypeExcludeFilter(Class testClass) { super(testClass); diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/resources/META-INF/spring.factories b/spring-boot-project/spring-boot-test-autoconfigure/src/main/resources/META-INF/spring.factories index 00e9124d86f..f93ed7bbdb5 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/main/resources/META-INF/spring.factories +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/resources/META-INF/spring.factories @@ -6,6 +6,8 @@ org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration org.springframework.boot.test.autoconfigure.data.cassandra.AutoConfigureDataCassandra=\ org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\ org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\ +org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\ +org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration # AutoConfigureDataJdbc auto-configuration imports diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/actuate/metrics/AutoConfigureMetricsSpringBootApplication.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/actuate/metrics/AutoConfigureMetricsSpringBootApplication.java index 4337f2c7fdf..1520c1b9585 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/actuate/metrics/AutoConfigureMetricsSpringBootApplication.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/actuate/metrics/AutoConfigureMetricsSpringBootApplication.java @@ -19,6 +19,7 @@ package org.springframework.boot.test.autoconfigure.actuate.metrics; import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration; /** * Example {@link SpringBootApplication @SpringBootApplication} for use with @@ -27,7 +28,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; * @author Chris Bono */ @SpringBootConfiguration -@EnableAutoConfiguration +@EnableAutoConfiguration(exclude = CassandraAutoConfiguration.class) class AutoConfigureMetricsSpringBootApplication { } diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/DataCassandraTestIntegrationTests.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/DataCassandraTestIntegrationTests.java index 4be7e4f4285..bc8897966c7 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/DataCassandraTestIntegrationTests.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/DataCassandraTestIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -16,23 +16,25 @@ package org.springframework.boot.test.autoconfigure.data.cassandra; +import java.time.Duration; import java.util.UUID; -import com.datastax.driver.core.Cluster; +import com.datastax.oss.driver.api.core.CqlSession; +import com.datastax.oss.driver.api.core.CqlSessionBuilder; import org.junit.jupiter.api.Test; +import org.testcontainers.containers.CassandraContainer; import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.data.redis.ExampleService; -import org.springframework.boot.test.util.TestPropertyValues; -import org.springframework.boot.testsupport.testcontainers.CassandraContainer; -import org.springframework.boot.testsupport.testcontainers.DisabledWithoutDockerTestcontainers; +import org.springframework.boot.test.context.TestConfiguration; import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextInitializer; -import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.Bean; import org.springframework.data.cassandra.core.CassandraTemplate; -import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @@ -42,13 +44,21 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType; * * @author Artsiom Yudovin */ -@DisabledWithoutDockerTestcontainers -@ContextConfiguration(initializers = DataCassandraTestIntegrationTests.Initializer.class) -@DataCassandraTest +@DataCassandraTest(properties = { "spring.data.cassandra.local-datacenter=datacenter1", + "spring.data.cassandra.schema-action=create-if-not-exists", + "spring.data.cassandra.connection.connect-timeout=10s", "spring.data.cassandra.request.timeout=5s" }) +@Testcontainers(disabledWithoutDocker = true) class DataCassandraTestIntegrationTests { @Container - public static CassandraContainer cassandra = new CassandraContainer(); + static final CassandraContainer cassandra = new CassandraContainer<>().withStartupAttempts(5) + .withStartupTimeout(Duration.ofMinutes(10)); + + @DynamicPropertySource + static void cassandraProperties(DynamicPropertyRegistry registry) { + registry.add("spring.data.cassandra.contact-points", + () -> cassandra.getHost() + ":" + cassandra.getFirstMappedPort()); + } @Autowired private CassandraTemplate cassandraTemplate; @@ -67,36 +77,28 @@ class DataCassandraTestIntegrationTests { @Test void testRepository() { - - Person person = new Person(); - person.setDescription("Look, new @DataCassandraTest!"); + ExampleEntity entity = new ExampleEntity(); + entity.setDescription("Look, new @DataCassandraTest!"); String id = UUID.randomUUID().toString(); - person.setId(id); - - Person savedEntity = this.exampleRepository.save(person); - Person getEntity = this.cassandraTemplate.selectOneById(id, Person.class); - + entity.setId(id); + ExampleEntity savedEntity = this.exampleRepository.save(entity); + ExampleEntity getEntity = this.cassandraTemplate.selectOneById(id, ExampleEntity.class); assertThat(getEntity).isNotNull(); assertThat(getEntity.getId()).isNotNull(); assertThat(getEntity.getId()).isEqualTo(savedEntity.getId()); - this.exampleRepository.deleteAll(); } - static class Initializer implements ApplicationContextInitializer { - - @Override - public void initialize(ConfigurableApplicationContext configurableApplicationContext) { - TestPropertyValues.of("spring.data.cassandra.port=" + cassandra.getFirstMappedPort()) - .and("spring.data.cassandra.keyspaceName=test") - .and("spring.data.cassandra.schema-action=CREATE_IF_NOT_EXISTS") - .applyTo(configurableApplicationContext.getEnvironment()); + @TestConfiguration(proxyBeanMethods = false) + static class KeyspaceTestConfiguration { - Cluster cluster = Cluster.builder().withoutJMXReporting() - .addContactPoints(cassandra.getContainerIpAddress()).withPort(cassandra.getFirstMappedPort()) - .build(); - cluster.connect().execute("CREATE KEYSPACE test " - + "WITH replication = {'class':'SimpleStrategy', 'replication_factor' : 1};"); + @Bean + CqlSession cqlSession(CqlSessionBuilder cqlSessionBuilder) { + try (CqlSession session = cqlSessionBuilder.build()) { + session.execute("CREATE KEYSPACE IF NOT EXISTS boot_test" + + " WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 };"); + } + return cqlSessionBuilder.withKeyspace("boot_test").build(); } } diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/DataCassandraTestPropertiesIntegrationTests.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/DataCassandraTestPropertiesIntegrationTests.java index c8294f1dd23..3083322d6bc 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/DataCassandraTestPropertiesIntegrationTests.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/DataCassandraTestPropertiesIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -16,19 +16,19 @@ package org.springframework.boot.test.autoconfigure.data.cassandra; +import com.datastax.oss.driver.api.core.CqlSession; +import com.datastax.oss.driver.api.core.context.DriverContext; +import com.datastax.oss.driver.api.core.type.codec.registry.CodecRegistry; import org.junit.jupiter.api.Test; -import org.testcontainers.junit.jupiter.Container; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.util.TestPropertyValues; -import org.springframework.boot.testsupport.testcontainers.CassandraContainer; -import org.springframework.boot.testsupport.testcontainers.DisabledWithoutDockerTestcontainers; -import org.springframework.context.ApplicationContextInitializer; -import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; import org.springframework.core.env.Environment; -import org.springframework.test.context.ContextConfiguration; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; /** * Tests for the {@link DataCassandraTest#properties properties} attribute of @@ -36,14 +36,9 @@ import static org.assertj.core.api.Assertions.assertThat; * * @author Artsiom Yudovin */ -@DisabledWithoutDockerTestcontainers -@ContextConfiguration(initializers = DataCassandraTestPropertiesIntegrationTests.Initializer.class) @DataCassandraTest(properties = "spring.profiles.active=test") class DataCassandraTestPropertiesIntegrationTests { - @Container - public static final CassandraContainer cassandra = new CassandraContainer(); - @Autowired private Environment environment; @@ -52,12 +47,17 @@ class DataCassandraTestPropertiesIntegrationTests { assertThat(this.environment.getActiveProfiles()).containsExactly("test"); } - static class Initializer implements ApplicationContextInitializer { + @TestConfiguration(proxyBeanMethods = false) + static class CassandraMockConfiguration { - @Override - public void initialize(ConfigurableApplicationContext configurableApplicationContext) { - TestPropertyValues.of("spring.data.cassandra.port=" + cassandra.getFirstMappedPort()) - .applyTo(configurableApplicationContext.getEnvironment()); + @Bean + CqlSession cqlSession() { + DriverContext context = mock(DriverContext.class); + CodecRegistry codecRegistry = mock(CodecRegistry.class); + given(context.getCodecRegistry()).willReturn(codecRegistry); + CqlSession cqlSession = mock(CqlSession.class); + given(cqlSession.getContext()).willReturn(context); + return cqlSession; } } diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/DataCassandraTestWithIncludeFilterIntegrationTests.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/DataCassandraTestWithIncludeFilterIntegrationTests.java index 354e86f90dc..b1baff51ce8 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/DataCassandraTestWithIncludeFilterIntegrationTests.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/DataCassandraTestWithIncludeFilterIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -16,21 +16,23 @@ package org.springframework.boot.test.autoconfigure.data.cassandra; +import java.time.Duration; import java.util.UUID; -import com.datastax.driver.core.Cluster; +import com.datastax.oss.driver.api.core.CqlSession; +import com.datastax.oss.driver.api.core.CqlSessionBuilder; import org.junit.jupiter.api.Test; +import org.testcontainers.containers.CassandraContainer; import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.util.TestPropertyValues; -import org.springframework.boot.testsupport.testcontainers.CassandraContainer; -import org.springframework.boot.testsupport.testcontainers.DisabledWithoutDockerTestcontainers; -import org.springframework.context.ApplicationContextInitializer; -import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.stereotype.Service; -import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; import static org.assertj.core.api.Assertions.assertThat; @@ -40,13 +42,22 @@ import static org.assertj.core.api.Assertions.assertThat; * * @author Artsiom Yudovin */ -@DisabledWithoutDockerTestcontainers -@ContextConfiguration(initializers = DataCassandraTestWithIncludeFilterIntegrationTests.Initializer.class) -@DataCassandraTest(includeFilters = @Filter(Service.class)) +@DataCassandraTest(includeFilters = @Filter(Service.class), + properties = { "spring.data.cassandra.local-datacenter=datacenter1", + "spring.data.cassandra.schema-action=create-if-not-exists", + "spring.data.cassandra.connection.connect-timeout=10s", "spring.data.cassandra.request.timeout=5s" }) +@Testcontainers(disabledWithoutDocker = true) class DataCassandraTestWithIncludeFilterIntegrationTests { @Container - public static final CassandraContainer cassandra = new CassandraContainer(); + static final CassandraContainer cassandra = new CassandraContainer<>().withStartupAttempts(5) + .withStartupTimeout(Duration.ofMinutes(10)); + + @DynamicPropertySource + static void cassandraProperties(DynamicPropertyRegistry registry) { + registry.add("spring.data.cassandra.contact-points", + () -> cassandra.getHost() + ":" + cassandra.getFirstMappedPort()); + } @Autowired private ExampleRepository exampleRepository; @@ -56,30 +67,24 @@ class DataCassandraTestWithIncludeFilterIntegrationTests { @Test void testService() { - Person person = new Person(); - person.setDescription("Look, new @DataCassandraTest!"); + ExampleEntity exampleEntity = new ExampleEntity(); + exampleEntity.setDescription("Look, new @DataCassandraTest!"); String id = UUID.randomUUID().toString(); - person.setId(id); - - this.exampleRepository.save(person); - assertThat(this.service.hasRecord(person)).isTrue(); - + exampleEntity.setId(id); + this.exampleRepository.save(exampleEntity); + assertThat(this.service.hasRecord(exampleEntity)).isTrue(); } - static class Initializer implements ApplicationContextInitializer { - - @Override - public void initialize(ConfigurableApplicationContext configurableApplicationContext) { - TestPropertyValues.of("spring.data.cassandra.port=" + cassandra.getFirstMappedPort()) - .and("spring.data.cassandra.keyspaceName=test") - .and("spring.data.cassandra.schema-action=CREATE_IF_NOT_EXISTS") - .applyTo(configurableApplicationContext.getEnvironment()); + @TestConfiguration(proxyBeanMethods = false) + static class KeyspaceTestConfiguration { - Cluster cluster = Cluster.builder().withoutJMXReporting() - .addContactPoints(cassandra.getContainerIpAddress()).withPort(cassandra.getFirstMappedPort()) - .build(); - cluster.connect().execute("CREATE KEYSPACE test " - + "WITH replication = {'class':'SimpleStrategy', 'replication_factor' : 1};"); + @Bean + CqlSession cqlSession(CqlSessionBuilder cqlSessionBuilder) { + try (CqlSession session = cqlSessionBuilder.build()) { + session.execute("CREATE KEYSPACE IF NOT EXISTS boot_test" + + " WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 };"); + } + return cqlSessionBuilder.withKeyspace("boot_test").build(); } } diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/ExampleCassandraApplication.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/ExampleCassandraApplication.java index 385243d1b1f..a8459c979d6 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/ExampleCassandraApplication.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/ExampleCassandraApplication.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -22,7 +22,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; * Example {@link SpringBootApplication @SpringBootApplication} used with * {@link DataCassandraTest @DataCassandraTest} tests. * - * @author Jayaram Pradhan + * @author Artsiom Yudovin */ @SpringBootApplication public class ExampleCassandraApplication { diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/Person.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/ExampleEntity.java similarity index 93% rename from spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/Person.java rename to spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/ExampleEntity.java index 641a858cb63..17ea3354f09 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/Person.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/ExampleEntity.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -25,7 +25,7 @@ import org.springframework.data.cassandra.core.mapping.Table; * @author Artsiom Yudovin */ @Table -public class Person { +public class ExampleEntity { @PrimaryKey private String id; diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/ExampleRepository.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/ExampleRepository.java index c7da59d2513..261736170ac 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/ExampleRepository.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/ExampleRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -16,13 +16,13 @@ package org.springframework.boot.test.autoconfigure.data.cassandra; -import org.springframework.data.repository.CrudRepository; +import org.springframework.data.cassandra.repository.CassandraRepository; /** * Example repository used with {@link DataCassandraTest @DataCassandraTest} tests. * * @author Artsiom Yudovin */ -public interface ExampleRepository extends CrudRepository { +interface ExampleRepository extends CassandraRepository { } diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/ExampleService.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/ExampleService.java index dffb3b39d0f..1a5a49cde03 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/ExampleService.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/data/cassandra/ExampleService.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -33,8 +33,8 @@ public class ExampleService { this.cassandraTemplate = cassandraTemplate; } - public boolean hasRecord(Person person) { - return this.cassandraTemplate.exists(person.getId(), Person.class); + public boolean hasRecord(ExampleEntity entity) { + return this.cassandraTemplate.exists(entity.getId(), ExampleEntity.class); } } diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/json/app/ExampleJsonApplication.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/json/app/ExampleJsonApplication.java index 2e21f9bcbc9..7f63af309b7 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/json/app/ExampleJsonApplication.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/json/app/ExampleJsonApplication.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -17,6 +17,7 @@ package org.springframework.boot.test.autoconfigure.json.app; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration; import org.springframework.boot.test.autoconfigure.json.JsonTest; /** @@ -25,7 +26,7 @@ import org.springframework.boot.test.autoconfigure.json.JsonTest; * * @author Phillip Webb */ -@SpringBootApplication +@SpringBootApplication(exclude = CassandraAutoConfiguration.class) public class ExampleJsonApplication { } diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/override/OverrideAutoConfigurationSpringBootApplication.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/override/OverrideAutoConfigurationSpringBootApplication.java index c519802da98..803e999ae41 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/override/OverrideAutoConfigurationSpringBootApplication.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/override/OverrideAutoConfigurationSpringBootApplication.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -19,6 +19,7 @@ package org.springframework.boot.test.autoconfigure.override; import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration; import org.springframework.boot.test.autoconfigure.OverrideAutoConfiguration; /** @@ -28,7 +29,7 @@ import org.springframework.boot.test.autoconfigure.OverrideAutoConfiguration; * @author Andy Wilkinson */ @SpringBootConfiguration -@EnableAutoConfiguration +@EnableAutoConfiguration(exclude = CassandraAutoConfiguration.class) public class OverrideAutoConfigurationSpringBootApplication { } diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsTestApplication.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsTestApplication.java index c62c85d0646..c2134a1b2e7 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsTestApplication.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/restdocs/RestDocsTestApplication.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -18,6 +18,7 @@ package org.springframework.boot.test.autoconfigure.restdocs; import org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration; import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; /** @@ -25,7 +26,8 @@ import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfi * * @author Andy Wilkinson */ -@SpringBootApplication(exclude = { SecurityAutoConfiguration.class, ManagementWebSecurityAutoConfiguration.class }) +@SpringBootApplication(exclude = { CassandraAutoConfiguration.class, SecurityAutoConfiguration.class, + ManagementWebSecurityAutoConfiguration.class }) public class RestDocsTestApplication { } diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/web/client/AutoConfigureWebClientWithRestTemplateIntegrationTests.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/web/client/AutoConfigureWebClientWithRestTemplateIntegrationTests.java index a8fa93e2ddc..edb53b36e47 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/web/client/AutoConfigureWebClientWithRestTemplateIntegrationTests.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/web/client/AutoConfigureWebClientWithRestTemplateIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -20,6 +20,7 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration; import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Configuration; @@ -57,7 +58,7 @@ class AutoConfigureWebClientWithRestTemplateIntegrationTests { } @Configuration(proxyBeanMethods = false) - @EnableAutoConfiguration + @EnableAutoConfiguration(exclude = CassandraAutoConfiguration.class) static class Config { } diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/web/reactive/webclient/ExampleWebFluxApplication.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/web/reactive/webclient/ExampleWebFluxApplication.java index e20ef486679..124d8c36a3e 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/web/reactive/webclient/ExampleWebFluxApplication.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/web/reactive/webclient/ExampleWebFluxApplication.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -17,6 +17,7 @@ package org.springframework.boot.test.autoconfigure.web.reactive.webclient; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration; import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest; /** @@ -25,7 +26,7 @@ import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest; * * @author Stephane Nicoll */ -@SpringBootApplication +@SpringBootApplication(exclude = CassandraAutoConfiguration.class) public class ExampleWebFluxApplication { } diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/web/servlet/mockmvc/ExampleWebMvcApplication.java b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/web/servlet/mockmvc/ExampleWebMvcApplication.java index 73513d58fdc..fc2f85bd7bb 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/web/servlet/mockmvc/ExampleWebMvcApplication.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/web/servlet/mockmvc/ExampleWebMvcApplication.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 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. @@ -17,6 +17,7 @@ package org.springframework.boot.test.autoconfigure.web.servlet.mockmvc; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; /** @@ -25,7 +26,7 @@ import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; * * @author Phillip Webb */ -@SpringBootApplication +@SpringBootApplication(exclude = CassandraAutoConfiguration.class) public class ExampleWebMvcApplication { } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/testcontainers/CassandraContainer.java b/spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/testcontainers/CassandraContainer.java deleted file mode 100644 index e24ec00f6c5..00000000000 --- a/spring-boot-project/spring-boot-tools/spring-boot-test-support/src/main/java/org/springframework/boot/testsupport/testcontainers/CassandraContainer.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2012-2018 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 - * - * https://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 org.testcontainers.containers.GenericContainer; - -/** - * A {@link GenericContainer} for Redis. - * - * @author Artsiom Yudovin - * @since 2.1.0 - */ -public class CassandraContainer extends GenericContainer { - - public CassandraContainer() { - super("cassandra:3"); - addExposedPorts(9042); - } - -}