Skip to content

Commit

Permalink
feat(mongo): #10 add dbTracker to WithMongoData
Browse files Browse the repository at this point in the history
close #10
  • Loading branch information
Marthym committed Feb 3, 2024
1 parent ceafdf5 commit b08622f
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 8 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@

<java-inject.version>1</java-inject.version>
<jetbrains.version>24.0.1</jetbrains.version>
<junit.version>5.10.0</junit.version>
<junit.version>5.10.1</junit.version>
<lombok.version>1.18.30</lombok.version>

<amqp-client.version>5.20.0</amqp-client.version>
Expand Down
4 changes: 4 additions & 0 deletions testy-mongo-box/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
</dependency>

<!--MONGO-->
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import de.flapdoodle.embed.mongo.transitions.RunningMongodProcess;
import de.flapdoodle.embed.process.io.ProcessOutput;
import de.flapdoodle.reverse.transitions.Start;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.extension.AfterAllCallback;
import org.junit.jupiter.api.extension.BeforeAllCallback;
Expand Down Expand Up @@ -40,12 +41,13 @@
public class WithEmbeddedMongo implements BeforeAllCallback, AfterAllCallback, ParameterResolver {
private static final Namespace NAMESPACE = Namespace.create(WithEmbeddedMongo.class);

public static final String P_MONGO_DB_NAME = "mongoDbName";
private static final String P_MONGO_PROCESS = "mongoPocess";
private static final String P_MONGO_CLIENT = "mongoClient";
private static final String P_MONGO_FACTORY = "reactiveMongoFactory";
private static final String P_MONGO_TEMPLATE = "reactiveMongoTemplate";
private static final String P_MONGO_DB_NAME = "mongoDbName";

@Getter
private final String databaseName;
private final AtomicReference<ReactiveMongoDatabaseFactory> atomicMongoFactory;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,21 @@
import org.bson.Document;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.BeforeEachCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ParameterContext;
import org.junit.jupiter.api.extension.ParameterResolver;
import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
import reactor.core.publisher.Mono;

import javax.inject.Named;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;

/**
* Extension allowing to initialize a mongo database with data.
Expand Down Expand Up @@ -77,9 +83,22 @@
* // (...)
* }
* </pre>
*
* <h2>Database Tracker</h2>
* <p>For performance reasons, the lib provides a {@link Tracker} that lets the extension know that the database has
* not been modified, and that it is therefore not necessary to recreate all the collections.</p>
*
* <pre><code>
* {@literal @}Test
* void should_read_data(WithMongoData.Tracker tracker) {
* tracker.skipNextSampleLoad();
* ...
* }
* </code></pre>
*/
public final class WithMongoData implements BeforeEachCallback {
public final class WithMongoData implements BeforeEachCallback, BeforeAllCallback, ParameterResolver {
private static final String MONGO_ID_FIELD = "_id";
private static final String P_TRACKER = "sampleTracker_";

private final WithEmbeddedMongo wEmbeddedMongo;
private final @Nullable WithObjectMapper wObjectMapper;
Expand All @@ -100,20 +119,61 @@ private WithMongoData(WithEmbeddedMongo wEmbeddedMongo,
this.dataSets = dataSets;
}

@Override
public void beforeAll(ExtensionContext context) {
String dbName = wEmbeddedMongo.getDatabaseName();
getStore(context).put(P_TRACKER + dbName, new Tracker());
}

@Override
public void beforeEach(ExtensionContext context) {
final ObjectMapper objectMapper = Optional.ofNullable(this.wObjectMapper)
.map(wom -> wom.getObjectMapper(context))
.orElseGet(ObjectMapper::new);
final ReactiveMongoTemplate mongoTemplate = this.wEmbeddedMongo.getMongoTemplate(context);
final Tracker tracker = getStore(context).get(P_TRACKER + this.wEmbeddedMongo.getDatabaseName(), Tracker.class);

if (tracker == null) {
throw new IllegalStateException(getClass().getName() + " must be static and package-protected !");
} else if (tracker.skipNext.getAndSet(false)) {
return;
}

dataSets.forEach((collection, dataSet) -> {
mongoTemplate.dropCollection(collection).block();
fillCollection(mongoTemplate, objectMapper, collection, dataSet);
});
}

@Override
public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext context) {
Class<?> type = parameterContext.getParameter().getType();
final String dbName = wEmbeddedMongo.getDatabaseName();
return Tracker.class.equals(type) && dbName.equals(getCatalogForParameter(parameterContext, dbName));
}

@Override
public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
Class<?> type = parameterContext.getParameter().getType();
final String dbName = wEmbeddedMongo.getDatabaseName();
if (Tracker.class.equals(type)) {
return getStore(extensionContext).get(P_TRACKER + dbName);
}

throw new NoSuchElementException(P_TRACKER + dbName);
}

private String getCatalogForParameter(ParameterContext parameterContext, String dbName) {
return parameterContext.findAnnotation(Named.class)
.map(Named::value)
.orElse(dbName);
}

private ExtensionContext.Store getStore(ExtensionContext context) {
String dbName = wEmbeddedMongo.getDatabaseName();
return context.getStore(ExtensionContext.Namespace.create(getClass().getName(), dbName));
}

private void fillCollection(ReactiveMongoTemplate mongoDb, ObjectMapper objectMapper, String collectionName, MongoDataSet<?> dataSet) {
final List<Document> toInsert = dataSet.documents().stream()
.map(o -> {
Expand Down Expand Up @@ -190,4 +250,12 @@ public WithMongoData build() {
.orElseGet(() -> new WithMongoData(wEmbeddedMongo, Map.copyOf(dataSetsBuilder)));
}
}

public static class Tracker {
private final AtomicBoolean skipNext = new AtomicBoolean(false);

public void skipNextSampleLoad() {
skipNext.set(true);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
import fr.ght1pc9kc.testy.mongo.sample.DocumentDataSet;
import org.bson.Document;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
Expand All @@ -18,16 +21,15 @@

import static org.assertj.core.api.Assertions.assertThat;

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class WithMongoDataTest {

private static final String COLLECTION_0 = "firstCollection";
private static final String COLLECTION_1 = "secondCollection";
private static final String COLLECTION_2 = "dummyCollection";

private static final WithEmbeddedMongo WITH_EMBEDDED_MONGO = WithEmbeddedMongo.builder()
.build();
private static final WithObjectMapper WITH_OBJECT_MAPPER = WithObjectMapper.builder()
.build();
private static final WithEmbeddedMongo WITH_EMBEDDED_MONGO = WithEmbeddedMongo.builder().build();
private static final WithObjectMapper WITH_OBJECT_MAPPER = WithObjectMapper.builder().build();
private static final WithMongoData WITH_MONGO_DATA = WithMongoData.builder(WITH_EMBEDDED_MONGO)
.withObjectMapper(WITH_OBJECT_MAPPER)
.addDataset(COLLECTION_0, new DocumentDataSet())
Expand All @@ -49,6 +51,7 @@ void setUp(ReactiveMongoTemplate mongoTemplate) {
this.mongoTemplate = mongoTemplate;
}

@Order(1)
@ParameterizedTest
@ValueSource(strings = {
COLLECTION_0,
Expand All @@ -66,13 +69,32 @@ void should_have_inserted_data(String collectionName) {
}

@Test
void should_have_inserted_clazz_data() {
@Order(2)
void should_have_inserted_clazz_data(WithMongoData.Tracker tracker) {
tracker.skipNextSampleLoad();

final List<Document> actual = mongoTemplate.findAll(Document.class, COLLECTION_2)
.collectList()
.block();

assertThat(actual).containsExactly(
new Document(Map.of("_id", "Luke", "bar", "Skywalker")),
new Document(Map.of("_id", "Obiwan", "bar", "Kenobi")));

mongoTemplate.insert(new Document(Map.of("_id", "Darth", "name", "Vader")), COLLECTION_2)
.block();
}

@Test
@Order(3)
void should_skip_reset_data() {
final List<Document> actual = mongoTemplate.findAll(Document.class, COLLECTION_2)
.collectList()
.block();

assertThat(actual).containsExactly(
new Document(Map.of("_id", "Luke", "bar", "Skywalker")),
new Document(Map.of("_id", "Obiwan", "bar", "Kenobi")),
new Document(Map.of("_id", "Darth", "name", "Vader")));
}
}

0 comments on commit b08622f

Please sign in to comment.