Skip to content

Commit 8603bb4

Browse files
authored
Merge pull request #38 from zonkyio/multiple-datasources
#33 Support repeatable @AutoConfigureEmbeddedDatabase annotations
2 parents 964f408 + 15dca5a commit 8603bb4

File tree

8 files changed

+336
-64
lines changed

8 files changed

+336
-64
lines changed

README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,31 @@ public class EmptyDatabaseIntegrationTest {
7171
}
7272
```
7373

74+
### Creating multiple independent databases
75+
76+
Because the `@AutoConfigureEmbeddedDatabase` is a repeatable annotation, you can annotate a test class with multiple annotations to create multiple independent databases.
77+
Each of them may have completely different configuration parameters, including the database provider as demonstrated in the example below.
78+
79+
Note that if multiple annotations on a single class are applied, some optimization techniques can not be used and database initialization may be slower.
80+
81+
```java
82+
@RunWith(SpringRunner.class)
83+
@AutoConfigureEmbeddedDatabase(beanName = "dataSource1")
84+
@AutoConfigureEmbeddedDatabase(beanName = "dataSource2")
85+
@AutoConfigureEmbeddedDatabase(beanName = "dataSource3", provider = DOCKER)
86+
public class MultipleDatabasesIntegrationTest {
87+
88+
@Autowired
89+
private DataSource dataSource1;
90+
@Autowired
91+
private DataSource dataSource2;
92+
@Autowired
93+
private DataSource dataSource3;
94+
95+
// class body...
96+
}
97+
```
98+
7499
### Using `@FlywayTest` annotation on a test class
75100

76101
The library supports the use of `@FlywayTest` annotation. If you use it, the embedded database will be automatically initialized and cleaned by Flyway database migration tool. If you don't specify any custom migration locations the default path `db/migration` will be applied.

embedded-database-spring-test/src/main/java/io/zonky/test/db/AutoConfigureEmbeddedDatabase.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,16 @@
2020
import java.lang.annotation.Documented;
2121
import java.lang.annotation.ElementType;
2222
import java.lang.annotation.Inherited;
23+
import java.lang.annotation.Repeatable;
2324
import java.lang.annotation.Retention;
2425
import java.lang.annotation.RetentionPolicy;
2526
import java.lang.annotation.Target;
2627

2728
/**
2829
* Annotation that can be applied to a test class to configure an embedded database to use
2930
* instead of any application defined {@link DataSource}.
31+
* <p>
32+
* This annotation may be used as a <em>meta-annotation</em> to create custom <em>composed annotations</em>.
3033
*
3134
* @see io.zonky.test.db.postgres.EmbeddedPostgresContextCustomizerFactory
3235
* @see io.zonky.test.db.flyway.OptimizedFlywayTestExecutionListener
@@ -35,6 +38,7 @@
3538
@Inherited
3639
@Target(ElementType.TYPE)
3740
@Retention(RetentionPolicy.RUNTIME)
41+
@Repeatable(AutoConfigureEmbeddedDatabases.class)
3842
public @interface AutoConfigureEmbeddedDatabase {
3943

4044
/**
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright 2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.zonky.test.db;
18+
19+
import java.lang.annotation.Documented;
20+
import java.lang.annotation.ElementType;
21+
import java.lang.annotation.Inherited;
22+
import java.lang.annotation.Retention;
23+
import java.lang.annotation.RetentionPolicy;
24+
import java.lang.annotation.Target;
25+
26+
/**
27+
* Container annotation that aggregates several {@link AutoConfigureEmbeddedDatabase} annotations.
28+
* <p>
29+
* Can be used natively, declaring several nested {@link AutoConfigureEmbeddedDatabase} annotations.
30+
* Can also be used in conjunction with Java 8's support for <em>repeatable annotations</em>,
31+
* where {@link AutoConfigureEmbeddedDatabase} can simply be declared several times on the same
32+
* {@linkplain ElementType#TYPE type}, implicitly generating this container annotation.
33+
* <p>
34+
* This annotation may be used as a <em>meta-annotation</em> to create custom <em>composed annotations</em>.
35+
*
36+
* @see AutoConfigureEmbeddedDatabase
37+
*/
38+
@Documented
39+
@Inherited
40+
@Target(ElementType.TYPE)
41+
@Retention(RetentionPolicy.RUNTIME)
42+
public @interface AutoConfigureEmbeddedDatabases {
43+
44+
AutoConfigureEmbeddedDatabase[] value();
45+
46+
}

embedded-database-spring-test/src/main/java/io/zonky/test/db/flyway/DefaultFlywayDataSourceContext.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,7 @@
1818

1919
import io.zonky.test.db.provider.DatabaseDescriptor;
2020
import io.zonky.test.db.provider.DatabasePreparer;
21-
import io.zonky.test.db.provider.DatabaseType;
2221
import io.zonky.test.db.provider.GenericDatabaseProvider;
23-
import io.zonky.test.db.provider.ProviderType;
2422
import org.apache.commons.lang3.exception.ExceptionUtils;
2523
import org.flywaydb.core.Flyway;
2624
import org.springframework.beans.factory.annotation.Autowired;
@@ -63,6 +61,8 @@ public class DefaultFlywayDataSourceContext implements FlywayDataSourceContext {
6361
@Autowired
6462
protected GenericDatabaseProvider databaseProvider;
6563

64+
protected DatabaseDescriptor databaseDescriptor;
65+
6666
protected int maxAttempts = DEFAULT_MAX_RETRY_ATTEMPTS;
6767

6868
protected TaskExecutor bootstrapExecutor;
@@ -98,17 +98,20 @@ public void releaseTarget(Object target) {
9898
// nothing to do
9999
}
100100

101+
@Override
102+
public void setDescriptor(DatabaseDescriptor descriptor) {
103+
this.databaseDescriptor = descriptor;
104+
}
105+
101106
@Override
102107
public synchronized ListenableFuture<DataSource> reload(Flyway flyway) {
103108
Executor executor = bootstrapExecutor != null ? bootstrapExecutor : Runnable::run;
104109

105110
CompletableFuture<DataSource> reloadFuture = dataSourceFuture.thenApplyAsync(x -> {
106111
for (int current = 1; current <= maxAttempts; current++) {
107112
try {
108-
String providerName = environment.getProperty("embedded-database.provider", ProviderType.ZONKY.toString());
109-
FlywayDatabasePreparer preparer = new FlywayDatabasePreparer(flyway);
110-
DatabaseDescriptor descriptor = new DatabaseDescriptor(DatabaseType.POSTGRES, ProviderType.valueOf(providerName));
111-
return databaseProvider.getDatabase(preparer, descriptor);
113+
FlywayDatabasePreparer databasePreparer = new FlywayDatabasePreparer(flyway);
114+
return databaseProvider.getDatabase(databasePreparer, databaseDescriptor);
112115
} catch (Exception e) {
113116
if (ExceptionUtils.indexOfType(e, IOException.class) == -1 || current == maxAttempts) {
114117
throw new CompletionException(e);

embedded-database-spring-test/src/main/java/io/zonky/test/db/flyway/FlywayDataSourceContext.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package io.zonky.test.db.flyway;
1818

19+
import io.zonky.test.db.provider.DatabaseDescriptor;
1920
import org.flywaydb.core.Flyway;
2021
import org.springframework.aop.TargetSource;
2122
import org.springframework.util.concurrent.ListenableFuture;
@@ -30,4 +31,6 @@ public interface FlywayDataSourceContext extends TargetSource {
3031

3132
ListenableFuture<DataSource> reload(Flyway flyway);
3233

34+
void setDescriptor(DatabaseDescriptor descriptor);
35+
3336
}

0 commit comments

Comments
 (0)