diff --git a/src/main/java/de/ozgcloud/aggregation/AggregationManagerRunner.java b/src/main/java/de/ozgcloud/aggregation/AggregationManagerRunner.java
index ccfe40139c90b6f80ff097426b707ad7515f42ce..3cd83a1ba1130ed10ce21e2466db8abc71e47955 100644
--- a/src/main/java/de/ozgcloud/aggregation/AggregationManagerRunner.java
+++ b/src/main/java/de/ozgcloud/aggregation/AggregationManagerRunner.java
@@ -23,37 +23,19 @@
  */
 package de.ozgcloud.aggregation;
 
-import java.util.List;
 import java.util.Objects;
-import java.util.Optional;
 import java.util.UUID;
-import java.util.function.Function;
-import java.util.function.IntFunction;
-import java.util.function.IntPredicate;
-import java.util.function.Predicate;
-import java.util.function.UnaryOperator;
-import java.util.stream.IntStream;
-import java.util.stream.Stream;
 
-import org.apache.logging.log4j.CloseableThreadContext;
 import org.apache.logging.log4j.ThreadContext;
+import org.springframework.beans.factory.annotation.Lookup;
 import org.springframework.boot.CommandLineRunner;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.stereotype.Component;
 
-import de.ozgcloud.aggregation.transformation.AggregationMapping.FormIdentifier;
+import de.ozgcloud.aggregation.transformation.AggregationMapping;
 import de.ozgcloud.aggregation.transformation.Transformation;
 import de.ozgcloud.aggregation.transformation.TransformationException;
 import de.ozgcloud.aggregation.transformation.TransformationService;
-import de.ozgcloud.aggregation.transformation.VorgangMapper;
-import de.ozgcloud.aggregation.warehouse.DocumentEntry;
-import de.ozgcloud.aggregation.warehouse.WarehouseRepository;
-import de.ozgcloud.apilib.vorgang.OzgCloudVorgang;
-import de.ozgcloud.apilib.vorgang.OzgCloudVorgangQuery;
-import de.ozgcloud.apilib.vorgang.OzgCloudVorgangQuery.FormIdentification;
-import de.ozgcloud.apilib.vorgang.OzgCloudVorgangService;
-import de.ozgcloud.apilib.vorgang.OzgCloudVorgangStub;
-import de.ozgcloud.apilib.vorgang.Page;
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.log4j.Log4j2;
@@ -62,133 +44,54 @@ import lombok.extern.log4j.Log4j2;
 @RequiredArgsConstructor
 @Log4j2
 @ConditionalOnProperty(prefix = "ozgcloud.command.line.runner", value = "enabled", havingValue = "true", matchIfMissing = true)
-public class AggregationManagerRunner implements CommandLineRunner {
+public abstract class AggregationManagerRunner implements CommandLineRunner {
 
 	private static final String MDC_EXECUTION = "execution";
-	private static final String MDC_VORGANG = "vorgang";
 
-	private static final Predicate<Batch> HAS_NEXT_BATCH = x -> !x.items.isEmpty();
-
-	private final OzgCloudVorgangService vorgangService;
 	private final AggregationManagerConfiguration config;
-
 	private final TransformationProperties transformationProperties;
-
 	private final TransformationService transformationService;
-	private final WarehouseRepository repository;
-	private final VorgangMapper vorgangMapper;
 
 	@Override
 	public void run(String... args) throws TransformationException {
 		var identifier = transformationProperties.getIdentifier();
 		var aggregationMappings = transformationProperties.getAggregationMappings();
 		if (Objects.isNull(aggregationMappings) || aggregationMappings.isEmpty()) {
-			runWithTransformation(transformationService.load(identifier, null), Optional.empty());
+			runWithDefaultTransformation(transformationService.load(identifier, null));
 		} else {
 			aggregationMappings.stream()
 					.forEach(aggregationMapping -> runWithTransformation(transformationService.load(identifier, aggregationMapping),
-							Optional.of(aggregationMapping.getFormIdentifier())));
+							aggregationMapping));
 		}
 	}
 
-	void runWithTransformation(Transformation transformation, Optional<FormIdentifier> formIdentifier) {
+	void runWithDefaultTransformation(Transformation transformation) {
+		runWithTransformation(transformation, null);
+	}
+
+	void runWithTransformation(Transformation transformation, AggregationMapping aggregationMapping) {
 		try (Execution execution = new Execution(transformation)) {
 			ThreadContext.put(MDC_EXECUTION, execution.id.toString());
-			loadVorgaengeIntoRepository(Stream.concat(
-					extractBatchesOfVorgaengeFromDataSource(execution, formIdentifier),
-					extractBatchesOfDeletedVorgaengeFromDataSource(execution, formIdentifier)));
+			prepareAggregator(execution, aggregationMapping).aggregate();
 		} finally {
 			ThreadContext.remove(MDC_EXECUTION);
 		}
 	}
 
-	void loadVorgaengeIntoRepository(Stream<Batch> batches) {
-		repository.deleteAll();
-		batches.map(this::transformBatchToDocumentEntries).forEach(this::loadDocumentEntriesIntoRepository);
-	}
-
-	Stream<Batch> extractBatchesOfVorgaengeFromDataSource(Execution execution, Optional<FormIdentifier> formIdentifier) {
-		return extractBatchesFromDataSource(execution, page -> getVorgaengeFromDataSource(page, formIdentifier));
-	}
-
-	List<OzgCloudVorgang> getVorgaengeFromDataSource(Page page, Optional<FormIdentifier> formIdentifier) {
-		return vorgangService.find(buildFindByFormEngineQuery(formIdentifier), page).stream()
-				.map(vorgangStub -> vorgangService.getById(vorgangStub.getId()))
-				.toList();
-	}
-
-	OzgCloudVorgangQuery buildFindByFormEngineQuery(Optional<FormIdentifier> formIdentifier) {
-		return OzgCloudVorgangQuery.builder()
-				.form(mapToFormIdentification(formIdentifier))
-				.build();
-	}
-
-	private Optional<FormIdentification> mapToFormIdentification(Optional<FormIdentifier> formIdentifier) {
-		return formIdentifier
-				.map(identifier -> FormIdentification.builder()
-						.formId(identifier.getFormId())
-						.formEngineName(identifier.getFormEngineName())
-						.build());
-	}
-
-	Stream<Batch> extractBatchesOfDeletedVorgaengeFromDataSource(Execution execution, Optional<FormIdentifier> formIdentifier) {
-		return formIdentifier.isEmpty() ? extractBatchesFromDataSource(execution, getPagedDeletedVorgaenge(vorgangService.findDeleted()))
-				: Stream.empty();
+	Aggregator prepareAggregator(Execution execution, AggregationMapping aggregationMapping) {
+		return createAggregator()
+				.withExecution(execution)
+				.withAggregationMapping(aggregationMapping)
+				.withBatchSize(config.getFetchingBatchSize());
 	}
 
-	Function<Page, List<OzgCloudVorgang>> getPagedDeletedVorgaenge(Stream<OzgCloudVorgangStub> allDeletedVorgaenge) {
-		var it = allDeletedVorgaenge.iterator();
-		IntPredicate hasNextVorgangStub = ignored -> it.hasNext();
-		IntFunction<OzgCloudVorgangStub> nextVorgangStub = ignored -> it.next();
-		return page -> IntStream.range(page.getOffset(), page.getOffset() + page.getLimit())
-				.takeWhile(hasNextVorgangStub)
-				.mapToObj(nextVorgangStub)
-				.map(vorgangMapper::fromVorgangStub)
-				.toList();
-	}
-
-	Stream<Batch> extractBatchesFromDataSource(Execution execution, Function<Page, List<OzgCloudVorgang>> getFromDataSource) {
-		var fetchSize = config.getFetchingBatchSize();
-		var initialBatch = createBatch(execution, Page.builder().offset(0).limit(fetchSize).build(), getFromDataSource);
-		UnaryOperator<Batch> nextBatch = x -> createBatch(
-				execution,
-				Page.builder().offset(x.page.getOffset() + fetchSize).limit(fetchSize).build(),
-				getFromDataSource);
-		return Stream.iterate(initialBatch, HAS_NEXT_BATCH, nextBatch).filter(x -> !x.items.isEmpty());
-	}
-
-	private Batch createBatch(Execution execution, Page page, Function<Page, List<OzgCloudVorgang>> getFromDataSource) {
-		return new Batch(execution, createBatchUUID(), page, getFromDataSource.apply(page));
-	}
-
-	UUID createBatchUUID() {
-		return UUID.randomUUID();
-	}
-
-	void loadDocumentEntriesIntoRepository(Stream<DocumentEntry> entries) {
-		final List<DocumentEntry> documents = entries.toList();
-		LOG.atDebug().log("store documents: {}", () -> documents.stream().map(DocumentEntry::getId).toList());
-		repository.saveAll(documents);
-	}
-
-	Stream<DocumentEntry> transformBatchToDocumentEntries(Batch batch) {
-		return batch.items.stream().map(vorgang -> transformWithinBatch(batch, vorgang)).filter(Objects::nonNull);
-	}
-
-	DocumentEntry transformWithinBatch(Batch batch, OzgCloudVorgang vorgang) {
-		try (var instance = CloseableThreadContext.put(MDC_VORGANG, vorgang.getId().toString())) {
-			return batch.execution.transformation.apply(vorgang);
-		} catch (TransformationException e) {
-			LOG.atError().withThrowable(e).log("failed to transform vorgang [{}] in batch [{}] of execution [{}]",
-					vorgang::getId, () -> batch.id, () -> batch.execution.id);
-			return null;
-		}
-	}
+	@Lookup
+	protected abstract Aggregator createAggregator();
 
+	@Getter
 	@RequiredArgsConstructor
 	protected static class Execution implements AutoCloseable {
 		private final UUID id = UUID.randomUUID();
-		@Getter
 		private final Transformation transformation;
 
 		@Override
@@ -197,7 +100,4 @@ public class AggregationManagerRunner implements CommandLineRunner {
 		}
 	}
 
-	record Batch(Execution execution, UUID id, Page page, List<OzgCloudVorgang> items) {
-	}
-
 }
diff --git a/src/main/java/de/ozgcloud/aggregation/Aggregator.java b/src/main/java/de/ozgcloud/aggregation/Aggregator.java
new file mode 100644
index 0000000000000000000000000000000000000000..79cf481fe8871d780ceec13bb1b7564037d2fb0c
--- /dev/null
+++ b/src/main/java/de/ozgcloud/aggregation/Aggregator.java
@@ -0,0 +1,160 @@
+package de.ozgcloud.aggregation;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.UUID;
+import java.util.function.Function;
+import java.util.function.IntFunction;
+import java.util.function.IntPredicate;
+import java.util.function.Predicate;
+import java.util.function.UnaryOperator;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+
+import org.apache.logging.log4j.CloseableThreadContext;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+import de.ozgcloud.aggregation.AggregationManagerRunner.Execution;
+import de.ozgcloud.aggregation.transformation.AggregationMapping;
+import de.ozgcloud.aggregation.transformation.AggregationMapping.FormIdentifier;
+import de.ozgcloud.aggregation.transformation.TransformationException;
+import de.ozgcloud.aggregation.transformation.VorgangMapper;
+import de.ozgcloud.aggregation.warehouse.DocumentEntry;
+import de.ozgcloud.aggregation.warehouse.WarehouseRepository;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgang;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangQuery;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangQuery.FormIdentification;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangService;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangStub;
+import de.ozgcloud.apilib.vorgang.Page;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.log4j.Log4j2;
+
+@Component
+@Scope("prototype")
+@RequiredArgsConstructor
+@Log4j2
+class Aggregator {
+
+	private static final String MDC_VORGANG = "vorgang";
+	private static final Predicate<Batch> HAS_NEXT_BATCH = x -> !x.items.isEmpty();
+
+	private final OzgCloudVorgangService vorgangService;
+	private final WarehouseRepository repository;
+	private final VorgangMapper vorgangMapper;
+
+	private Execution execution;
+	private FormIdentifier formIdentifier;
+	private String collectionName = DocumentEntry.COLLECTION;
+	private int batchSize = 100;
+
+	public Aggregator withExecution(Execution execution) {
+		this.execution = execution;
+		return this;
+	}
+
+	public Aggregator withAggregationMapping(AggregationMapping aggregationMapping) {
+		if (Objects.nonNull(aggregationMapping)) {
+			this.formIdentifier = aggregationMapping.getFormIdentifier();
+			this.collectionName = aggregationMapping.getName();
+		}
+		return this;
+	}
+
+	public Aggregator withBatchSize(int batchSize) {
+		this.batchSize = batchSize;
+		return this;
+	}
+
+	public void aggregate() {
+		loadVorgaengeIntoRepository(Stream.concat(extractBatchesOfVorgaengeFromDataSource(), extractBatchesOfDeletedVorgaengeFromDataSource()));
+	}
+
+	Stream<Batch> extractBatchesOfVorgaengeFromDataSource() {
+		return extractBatchesFromDataSource(this::getVorgaengeFromDataSource);
+	}
+
+	List<OzgCloudVorgang> getVorgaengeFromDataSource(Page page) {
+		return vorgangService.find(buildFindByFormEngineQuery(), page).stream()
+				.map(vorgangStub -> vorgangService.getById(vorgangStub.getId()))
+				.toList();
+	}
+
+	OzgCloudVorgangQuery buildFindByFormEngineQuery() {
+		return OzgCloudVorgangQuery.builder()
+				.form(mapToFormIdentification())
+				.build();
+	}
+
+	private Optional<FormIdentification> mapToFormIdentification() {
+		return Optional.ofNullable(formIdentifier)
+				.map(identifier -> FormIdentification.builder()
+						.formId(identifier.getFormId())
+						.formEngineName(identifier.getFormEngineName())
+						.build());
+	}
+
+	Stream<Batch> extractBatchesOfDeletedVorgaengeFromDataSource() {
+		return Objects.isNull(formIdentifier) ? extractBatchesFromDataSource(getPagedDeletedVorgaenge(vorgangService.findDeleted()))
+				: Stream.empty();
+	}
+
+	Function<Page, List<OzgCloudVorgang>> getPagedDeletedVorgaenge(Stream<OzgCloudVorgangStub> allDeletedVorgaenge) {
+		var it = allDeletedVorgaenge.iterator();
+		IntPredicate hasNextVorgangStub = ignored -> it.hasNext();
+		IntFunction<OzgCloudVorgangStub> nextVorgangStub = ignored -> it.next();
+		return page -> IntStream.range(page.getOffset(), page.getOffset() + page.getLimit())
+				.takeWhile(hasNextVorgangStub)
+				.mapToObj(nextVorgangStub)
+				.map(vorgangMapper::fromVorgangStub)
+				.toList();
+	}
+
+	Stream<Batch> extractBatchesFromDataSource(Function<Page, List<OzgCloudVorgang>> getFromDataSource) {
+		var initialBatch = createBatch(execution, Page.builder().offset(0).limit(batchSize).build(), getFromDataSource);
+		UnaryOperator<Batch> nextBatch = x -> createBatch(
+				execution,
+				Page.builder().offset(x.page.getOffset() + batchSize).limit(batchSize).build(),
+				getFromDataSource);
+		return Stream.iterate(initialBatch, HAS_NEXT_BATCH, nextBatch).filter(x -> !x.items.isEmpty());
+	}
+
+	private Batch createBatch(Execution execution, Page page, Function<Page, List<OzgCloudVorgang>> getFromDataSource) {
+		return new Batch(execution, createBatchUUID(), page, getFromDataSource.apply(page));
+	}
+
+	UUID createBatchUUID() {
+		return UUID.randomUUID();
+	}
+
+	void loadVorgaengeIntoRepository(Stream<Batch> batches) {
+		repository.clearCollection(collectionName);
+		batches.map(this::transformBatchToDocumentEntries).forEach(this::loadDocumentEntriesIntoRepository);
+	}
+
+	List<DocumentEntry> transformBatchToDocumentEntries(Batch batch) {
+		return batch.items.stream().map(vorgang -> transformWithinBatch(batch, vorgang)).filter(Objects::nonNull).toList();
+	}
+
+	DocumentEntry transformWithinBatch(Batch batch, OzgCloudVorgang vorgang) {
+		try (var instance = CloseableThreadContext.put(MDC_VORGANG, vorgang.getId().toString())) {
+			return batch.execution.getTransformation().apply(vorgang);
+		} catch (TransformationException e) {
+			LOG.error(
+					"failed to transform vorgang [%s] in batch [%s] of execution [%s]".formatted(vorgang.getId(), batch.id, batch.execution.getId()),
+					e);
+			return null;
+		}
+	}
+
+	void loadDocumentEntriesIntoRepository(List<DocumentEntry> entries) {
+		LOG.atDebug().log("store documents: {}", () -> entries.stream().map(DocumentEntry::getId).toList());
+		repository.saveAllInCollection(entries, collectionName);
+	}
+
+	record Batch(Execution execution, UUID id, Page page, List<OzgCloudVorgang> items) {
+	}
+
+}
diff --git a/src/main/java/de/ozgcloud/aggregation/TransformationProperties.java b/src/main/java/de/ozgcloud/aggregation/TransformationProperties.java
index b639b4bd91893f94bef366a4f16122a7a8265103..aadc1cac0a74c6ceec10de99559e7c6862b2a84c 100644
--- a/src/main/java/de/ozgcloud/aggregation/TransformationProperties.java
+++ b/src/main/java/de/ozgcloud/aggregation/TransformationProperties.java
@@ -25,8 +25,11 @@ package de.ozgcloud.aggregation;
 
 import java.util.List;
 
+import jakarta.validation.Valid;
+
 import org.springframework.boot.context.properties.ConfigurationProperties;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.validation.annotation.Validated;
 
 import de.ozgcloud.aggregation.transformation.AggregationMapping;
 import lombok.Getter;
@@ -35,6 +38,7 @@ import lombok.extern.log4j.Log4j2;
 
 @ConfigurationProperties(prefix = "ozgcloud.aggregation")
 @Configuration
+@Validated
 @Getter
 @Setter
 @Log4j2
@@ -44,6 +48,7 @@ public class TransformationProperties {
 	 * List of field mapping definitions with a form specification to which the
 	 * field mappings should be applied
 	 */
+	@Valid
 	private List<AggregationMapping> aggregationMappings;
 
 	/*
diff --git a/src/main/java/de/ozgcloud/aggregation/transformation/AggregationMapping.java b/src/main/java/de/ozgcloud/aggregation/transformation/AggregationMapping.java
index d98c2350ef04f3920dc8d30f8ea4100236991d65..958811b512292fb3388433275fa7dde64b8eb167 100644
--- a/src/main/java/de/ozgcloud/aggregation/transformation/AggregationMapping.java
+++ b/src/main/java/de/ozgcloud/aggregation/transformation/AggregationMapping.java
@@ -25,6 +25,10 @@ package de.ozgcloud.aggregation.transformation;
 
 import java.util.List;
 
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+
 import lombok.Builder;
 import lombok.Getter;
 import lombok.Singular;
@@ -35,22 +39,31 @@ import lombok.ToString;
 @ToString
 public class AggregationMapping {
 
+	@NotBlank
+	private String name;
+	@NotNull
+	@Valid
 	private FormIdentifier formIdentifier;
 
 	@Singular
+	@Valid
 	private List<FieldMapping> fieldMappings;
 
 	@Getter
 	@Builder
 	public static class FormIdentifier {
+		@NotBlank
 		private String formEngineName;
+		@NotBlank
 		private String formId;
 	}
 
 	@Getter
 	@Builder
 	public static class FieldMapping {
+		@NotBlank
 		private String sourcePath;
+		@NotBlank
 		private String targetPath;
 	}
 }
diff --git a/src/main/java/de/ozgcloud/aggregation/warehouse/CustomWarehouseRepository.java b/src/main/java/de/ozgcloud/aggregation/warehouse/CustomWarehouseRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..0a312165a18ef10eab5ce9178e3c4ba6f4efc396
--- /dev/null
+++ b/src/main/java/de/ozgcloud/aggregation/warehouse/CustomWarehouseRepository.java
@@ -0,0 +1,12 @@
+package de.ozgcloud.aggregation.warehouse;
+
+import java.util.List;
+
+interface CustomWarehouseRepository {
+
+	DocumentEntry saveInCollection(DocumentEntry documentEntry, String collectionName);
+
+	List<DocumentEntry> saveAllInCollection(Iterable<DocumentEntry> documentEntries, String collectionName);
+
+	void clearCollection(String collectionName);
+}
diff --git a/src/main/java/de/ozgcloud/aggregation/warehouse/CustomWarehouseRepositoryImpl.java b/src/main/java/de/ozgcloud/aggregation/warehouse/CustomWarehouseRepositoryImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..a5169d606f6a6055943538d8ac02f8a0477716b1
--- /dev/null
+++ b/src/main/java/de/ozgcloud/aggregation/warehouse/CustomWarehouseRepositoryImpl.java
@@ -0,0 +1,30 @@
+package de.ozgcloud.aggregation.warehouse;
+
+import java.util.List;
+import java.util.stream.StreamSupport;
+
+import org.springframework.data.mongodb.core.MongoTemplate;
+
+import lombok.RequiredArgsConstructor;
+
+@RequiredArgsConstructor
+class CustomWarehouseRepositoryImpl implements CustomWarehouseRepository {
+
+	private final MongoTemplate mongoTemplate;
+
+	@Override
+	public List<DocumentEntry> saveAllInCollection(Iterable<DocumentEntry> documentEntries, String collectionName) {
+		return StreamSupport.stream(documentEntries.spliterator(), false).map(entry -> saveInCollection(entry, collectionName)).toList();
+	}
+
+	@Override
+	public DocumentEntry saveInCollection(DocumentEntry documentEntry, String collectionName) {
+		return mongoTemplate.save(documentEntry, collectionName);
+	}
+
+	@Override
+	public void clearCollection(String collectionName) {
+		mongoTemplate.dropCollection(collectionName);
+	}
+
+}
diff --git a/src/main/java/de/ozgcloud/aggregation/warehouse/DocumentEntry.java b/src/main/java/de/ozgcloud/aggregation/warehouse/DocumentEntry.java
index 0b17e778ea3b1874c261d40a2110961a21dd0029..8f368ac3845ce1d37eedfc408cf1e0b0b2ab7da3 100644
--- a/src/main/java/de/ozgcloud/aggregation/warehouse/DocumentEntry.java
+++ b/src/main/java/de/ozgcloud/aggregation/warehouse/DocumentEntry.java
@@ -40,7 +40,7 @@ import lombok.Getter;
 @TypeAlias("Vorgang")
 public class DocumentEntry {
 
-	static final String COLLECTION = "vorgang";
+	public static final String COLLECTION = "vorgang";
 
 	@Id
 	private String id;
diff --git a/src/main/java/de/ozgcloud/aggregation/warehouse/WarehouseRepository.java b/src/main/java/de/ozgcloud/aggregation/warehouse/WarehouseRepository.java
index f8bef952cdeeda6c19e7df8f928932f002a2ecbd..c31564a9a30e98564b181b174e3589510be7c12c 100644
--- a/src/main/java/de/ozgcloud/aggregation/warehouse/WarehouseRepository.java
+++ b/src/main/java/de/ozgcloud/aggregation/warehouse/WarehouseRepository.java
@@ -27,6 +27,6 @@ import org.springframework.data.mongodb.repository.MongoRepository;
 import org.springframework.stereotype.Repository;
 
 @Repository
-public interface WarehouseRepository extends MongoRepository<DocumentEntry, String> {
+public interface WarehouseRepository extends MongoRepository<DocumentEntry, String>, CustomWarehouseRepository {
 
 }
diff --git a/src/test/java/de/ozgcloud/aggregation/AggregationManagerRunnerTest.java b/src/test/java/de/ozgcloud/aggregation/AggregationManagerRunnerTest.java
index 1e578c804c4a8caa7022cce046ec08f37c059fcc..ef2a1f26bb2fdfbcdf47a5dcd7d2f6292f63b661 100644
--- a/src/test/java/de/ozgcloud/aggregation/AggregationManagerRunnerTest.java
+++ b/src/test/java/de/ozgcloud/aggregation/AggregationManagerRunnerTest.java
@@ -29,42 +29,26 @@ import static org.mockito.Mockito.*;
 
 import java.util.Collections;
 import java.util.List;
-import java.util.Optional;
-import java.util.UUID;
-import java.util.function.Function;
-import java.util.stream.Stream;
 
+import org.apache.commons.lang3.RandomUtils;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
-import org.mockito.ArgumentCaptor;
 import org.mockito.ArgumentMatcher;
-import org.mockito.Captor;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Spy;
 
 import com.thedeanda.lorem.LoremIpsum;
 
-import de.ozgcloud.aggregation.AggregationManagerRunner.Batch;
 import de.ozgcloud.aggregation.AggregationManagerRunner.Execution;
 import de.ozgcloud.aggregation.transformation.AggregationMapping;
-import de.ozgcloud.aggregation.transformation.AggregationMapping.FormIdentifier;
 import de.ozgcloud.aggregation.transformation.AggregationMappingTestFactory;
-import de.ozgcloud.aggregation.transformation.FormIdentifierTestFactory;
 import de.ozgcloud.aggregation.transformation.Transformation;
 import de.ozgcloud.aggregation.transformation.TransformationService;
 import de.ozgcloud.aggregation.transformation.VorgangMapper;
-import de.ozgcloud.aggregation.warehouse.DocumentEntry;
-import de.ozgcloud.aggregation.warehouse.DocumentEntryTestFactory;
 import de.ozgcloud.aggregation.warehouse.WarehouseRepository;
-import de.ozgcloud.apilib.vorgang.OzgCloudVorgang;
-import de.ozgcloud.apilib.vorgang.OzgCloudVorgangQuery;
 import de.ozgcloud.apilib.vorgang.OzgCloudVorgangService;
-import de.ozgcloud.apilib.vorgang.OzgCloudVorgangStub;
-import de.ozgcloud.apilib.vorgang.OzgCloudVorgangStubTestFactory;
-import de.ozgcloud.apilib.vorgang.OzgCloudVorgangTestFactory;
-import de.ozgcloud.apilib.vorgang.Page;
 
 class AggregationManagerRunnerTest {
 
@@ -80,9 +64,11 @@ class AggregationManagerRunnerTest {
 	private WarehouseRepository repository;
 	@Mock
 	private VorgangMapper vorgangMapper;
+	@Mock
+	private static Aggregator aggregator;
 	@Spy
 	@InjectMocks
-	private AggregationManagerRunner runner;
+	private AggregationManagerRunnerImpl runner;
 
 	@Nested
 	class TestRun {
@@ -135,8 +121,8 @@ class AggregationManagerRunnerTest {
 			void shouldRunWithTransformationForEachTransformation() {
 				runner.run();
 
-				verify(runner).runWithTransformation(firstTransformation, Optional.of(AggregationMappingTestFactory.FORM_IDENTIFIER));
-				verify(runner).runWithTransformation(secondTransformation, Optional.of(AggregationMappingTestFactory.FORM_IDENTIFIER));
+				verify(runner).runWithTransformation(firstTransformation, aggregationMappings.get(0));
+				verify(runner).runWithTransformation(secondTransformation, aggregationMappings.get(1));
 			}
 		}
 
@@ -159,10 +145,10 @@ class AggregationManagerRunnerTest {
 			}
 
 			@Test
-			void shouldCallRunWithTransformation() {
+			void shouldCallRunWithDefaultTransformation() {
 				runner.run();
 
-				verify(runner).runWithTransformation(transformation, Optional.empty());
+				verify(runner).runWithDefaultTransformation(transformation);
 			}
 		}
 
@@ -185,386 +171,124 @@ class AggregationManagerRunnerTest {
 			}
 
 			@Test
-			void shouldCallRunWithTransformation() {
+			void shouldCallRunWithDefaultTransformation() {
 				runner.run();
 
-				verify(runner).runWithTransformation(transformation, Optional.empty());
+				verify(runner).runWithDefaultTransformation(transformation);
 			}
 		}
 	}
 
 	@Nested
-	class TestRunWithTransformation {
+	class TestRunWithDefaultTransformation {
 
 		@Mock
 		private Transformation transformation;
-		private final ArgumentMatcher<Execution> hasTransformation = execution -> execution.getTransformation().equals(transformation);
-		private final Optional<FormIdentifier> formIdentifier = Optional.of(FormIdentifierTestFactory.create());
-		@Mock
-		private Batch batchOfVorgaenge;
-		@Mock
-		private Batch batchOfDeletedVorgaenge;
-		@Captor
-		private ArgumentCaptor<Stream<Batch>> batchStreamCaptor;
-
-		@BeforeEach
-		void init() {
-			doReturn(Stream.of(batchOfVorgaenge)).when(runner).extractBatchesOfVorgaengeFromDataSource(any(), any());
-			doReturn(Stream.of(batchOfDeletedVorgaenge)).when(runner).extractBatchesOfDeletedVorgaengeFromDataSource(any(), any());
-			doNothing().when(runner).loadVorgaengeIntoRepository(any());
-		}
 
 		@Test
-		void shouldExtractBatchesOfVorgaengeFromDataSource() {
-			runner.runWithTransformation(transformation, formIdentifier);
-
-			verify(runner).extractBatchesOfVorgaengeFromDataSource(argThat(hasTransformation), eq(formIdentifier));
-		}
+		void shouldCallRunWithTransformation() {
+			doNothing().when(runner).runWithTransformation(any(), any());
 
-		@Test
-		void shouldExtractBatchesOfDeletedVorgaengeFromDataSource() {
-			runner.runWithTransformation(transformation, formIdentifier);
+			runner.runWithDefaultTransformation(transformation);
 
-			verify(runner).extractBatchesOfDeletedVorgaengeFromDataSource(argThat(hasTransformation), eq(formIdentifier));
-		}
-
-		@Test
-		void shouldLoadVorgaengeIntoRepository() {
-			runner.runWithTransformation(transformation, formIdentifier);
-
-			verify(runner).loadVorgaengeIntoRepository(batchStreamCaptor.capture());
-			assertThat(batchStreamCaptor.getValue()).containsExactly(batchOfVorgaenge, batchOfDeletedVorgaenge);
+			verify(runner).runWithTransformation(eq(transformation), isNull());
 		}
 	}
 
 	@Nested
-	class TestLoadVorgaengeIntoRepository {
+	class TestRunWithTransformation {
 
 		@Mock
-		private Execution execution;
-		@Mock
-		private Batch batch;
-		private final DocumentEntry documentEntry = DocumentEntryTestFactory.create();
-		@Captor
-		private ArgumentCaptor<Stream<DocumentEntry>> documentEntriesCaptor;
+		private Transformation transformation;
+		private final AggregationMapping aggregationMapping = AggregationMappingTestFactory.create();
+		private final ArgumentMatcher<Execution> hasTransformation = execution -> execution.getTransformation().equals(transformation);
 
 		@BeforeEach
-		void init() {
-			doReturn(Stream.of(documentEntry)).when(runner).transformBatchToDocumentEntries(any());
-			doNothing().when(runner).loadDocumentEntriesIntoRepository(any());
-		}
-
-		@Test
-		void shouldDropCollection() {
-			loadVorgaengeIntoRepository();
-
-			verify(repository).deleteAll();
+		void mock() {
+			doReturn(aggregator).when(runner).prepareAggregator(any(), any());
 		}
 
 		@Test
-		void shouldTransform() {
-			loadVorgaengeIntoRepository();
+		void shouldCallPrepareAggregator() {
+			runWithTransformation();
 
-			verify(runner).transformBatchToDocumentEntries(batch);
+			verify(runner).prepareAggregator(argThat(hasTransformation), eq(aggregationMapping));
 		}
 
 		@Test
-		void shouldLoadIntoRepository() {
-			loadVorgaengeIntoRepository();
+		void shouldLoadAggregation() {
+			runWithTransformation();
 
-			verify(runner).loadDocumentEntriesIntoRepository(documentEntriesCaptor.capture());
-			assertThat(documentEntriesCaptor.getValue()).containsExactly(documentEntry);
+			verify(aggregator).aggregate();
 		}
 
-		private void loadVorgaengeIntoRepository() {
-			runner.loadVorgaengeIntoRepository(Stream.of(batch));
+		private void runWithTransformation() {
+			runner.runWithTransformation(transformation, aggregationMapping);
 		}
 	}
 
 	@Nested
-	class TestExtractBatchesOfVorgaengeFromDataSource {
+	class TestPrepareAggregator {
 
-		private final Optional<FormIdentifier> formIdentifier = Optional.of(FormIdentifierTestFactory.create());
 		@Mock
 		private Execution execution;
-		@Captor
-		private ArgumentCaptor<Function<Page, List<OzgCloudVorgang>>> functionToRetrieveDataCaptor;
-		@Mock
-		private Batch batch;
-		@Mock
-		private Page page;
+		private final AggregationMapping aggregationMapping = AggregationMappingTestFactory.create();
+		private final int batchSize = RandomUtils.insecure().randomInt();
 
 		@BeforeEach
-		void init() {
-			doReturn(Stream.of(batch)).when(runner).extractBatchesFromDataSource(any(), any());
-		}
-
-		@Test
-		void shouldExtract() {
-			runner.extractBatchesOfVorgaengeFromDataSource(execution, formIdentifier);
-
-			verify(runner).extractBatchesFromDataSource(eq(execution), any());
-		}
-
-		@Test
-		void shouldExtractWithDataRetrievalFunction() {
-			runner.extractBatchesOfVorgaengeFromDataSource(execution, formIdentifier);
-
-			verify(runner).extractBatchesFromDataSource(eq(execution), functionToRetrieveDataCaptor.capture());
-			functionToRetrieveDataCaptor.getValue().apply(page);
-			verify(runner).getVorgaengeFromDataSource(page, formIdentifier);
-		}
-
-		@Test
-		void shouldReturnExtractedBatches() {
-			var extracted = runner.extractBatchesOfVorgaengeFromDataSource(execution, formIdentifier);
-
-			assertThat(extracted).containsExactly(batch);
-		}
-	}
-
-	@Nested
-	class TestGetVorgaengeFromDataSource {
-
-		private final Page page = Page.builder().offset(10).limit(2).build();
-		private final Optional<FormIdentifier> formIdentifier = Optional.of(FormIdentifierTestFactory.create());
-		private final OzgCloudVorgangQuery query = OzgCloudVorgangQuery.builder().build();
-
-		@BeforeEach
-		void init() {
-			doReturn(query).when(runner).buildFindByFormEngineQuery(any());
-			when(vorgangService.find(any(), any())).thenReturn(List.of(OzgCloudVorgangStubTestFactory.create()));
-			when(vorgangService.getById(any())).thenReturn(OzgCloudVorgangTestFactory.create());
-		}
-
-		@Test
-		void shouldCallBuildFindByFormEngineQuery() {
-			getVorgaengeFromDataSource();
-
-			verify(runner).buildFindByFormEngineQuery(formIdentifier);
+		void mock() {
+			when(config.getFetchingBatchSize()).thenReturn(batchSize);
+			when(aggregator.withExecution(any())).thenReturn(aggregator);
+			when(aggregator.withAggregationMapping(any())).thenReturn(aggregator);
+			when(aggregator.withBatchSize(anyInt())).thenReturn(aggregator);
 		}
 
 		@Test
-		void shouldCallVorgangService() {
-			getVorgaengeFromDataSource();
+		void shouldGetBatchSize() {
+			runner.prepareAggregator(execution, aggregationMapping);
 
-			verify(vorgangService).find(query, page);
+			verify(config).getFetchingBatchSize();
 		}
 
 		@Test
-		void shouldGetVorgangDetails() {
-			getVorgaengeFromDataSource();
+		void shouldSetExecution() {
+			runner.prepareAggregator(execution, aggregationMapping);
 
-			verify(vorgangService).getById(OzgCloudVorgangTestFactory.ID);
+			verify(aggregator).withExecution(execution);
 		}
 
 		@Test
-		void shouldReturnVorgangDetails() {
-			var vorgaenge = getVorgaengeFromDataSource();
-
-			assertThat(vorgaenge).usingRecursiveFieldByFieldElementComparator().containsExactly(OzgCloudVorgangTestFactory.create());
-		}
-
-		private List<OzgCloudVorgang> getVorgaengeFromDataSource() {
-			return runner.getVorgaengeFromDataSource(page, formIdentifier);
-		}
-	}
-
-	@Nested
-	class TestBuildFindByFormEngineQuery {
-
-		@Nested
-		class TestOnEmptyFormIdentifier {
-
-			@Test
-			void shouldReturnFindAllQueryOnEmptyFormIdentifier() {
-				var query = runner.buildFindByFormEngineQuery(Optional.empty());
-
-				assertThat(query).usingRecursiveComparison().isEqualTo(OzgCloudVorgangQuery.builder().build());
-			}
-		}
-
-		@Nested
-		class TestOnFormIdentifierNotEmpty {
-
-			private final Optional<FormIdentifier> formIdentifier = Optional.of(FormIdentifierTestFactory.create());
-
-			@Test
-			void shouldSetFormIdInQuery() {
-				var query = runner.buildFindByFormEngineQuery(formIdentifier);
-
-				assertThat(query.getForm()).get().extracting("formId").isEqualTo(FormIdentifierTestFactory.FORM_ID);
-			}
-
-			@Test
-			void shouldSetFormEngineNameInQuery() {
-				var query = runner.buildFindByFormEngineQuery(formIdentifier);
+		void shouldSetAggregationMapping() {
+			runner.prepareAggregator(execution, aggregationMapping);
 
-				assertThat(query.getForm()).get().extracting("formEngineName").isEqualTo(FormIdentifierTestFactory.FORM_ENGINE_NAME);
-			}
-		}
-	}
-
-	@Nested
-	class TestExtractBatchesOfDeletedVorgaengeFromDataSource {
-
-		@Mock
-		private Execution execution;
-		@Mock
-		private Function<Page, List<OzgCloudVorgang>> functionToRetrieveData;
-		private final List<OzgCloudVorgangStub> deletedVorgaenge = List.of(OzgCloudVorgangStubTestFactory.create());
-		@Captor
-		private ArgumentCaptor<Stream<OzgCloudVorgangStub>> deletedVorgaengeCaptor;
-		@Mock
-		private Batch batch;
-
-		@Nested
-		class TestOnEmptyFormIdentifier {
-
-			@BeforeEach
-			void init() {
-				when(vorgangService.findDeleted()).thenReturn(deletedVorgaenge.stream());
-				doReturn(functionToRetrieveData).when(runner).getPagedDeletedVorgaenge(any());
-				doReturn(Stream.of(batch)).when(runner).extractBatchesFromDataSource(any(), any());
-			}
-
-			@Test
-			void shouldFindDeleted() {
-				runner.extractBatchesOfDeletedVorgaengeFromDataSource(execution, Optional.empty());
-
-				verify(vorgangService).findDeleted();
-			}
-
-			@Test
-			void shouldGetPagedDeletedVorgaenge() {
-				runner.extractBatchesOfDeletedVorgaengeFromDataSource(execution, Optional.empty());
-
-				verify(runner).getPagedDeletedVorgaenge(deletedVorgaengeCaptor.capture());
-				assertThat(deletedVorgaengeCaptor.getValue()).usingRecursiveFieldByFieldElementComparator()
-						.containsExactlyElementsOf(deletedVorgaenge);
-			}
-
-			@Test
-			void shouldExtractWithDataRetrievalFunction() {
-				runner.extractBatchesOfDeletedVorgaengeFromDataSource(execution, Optional.empty());
-
-				verify(runner).extractBatchesFromDataSource(execution, functionToRetrieveData);
-			}
-
-			@Test
-			void shouldReturnExtractedBatches() {
-				var extracted = runner.extractBatchesOfDeletedVorgaengeFromDataSource(execution, Optional.empty());
-
-				assertThat(extracted).containsExactly(batch);
-			}
+			verify(aggregator).withAggregationMapping(aggregationMapping);
 		}
 
-		@Nested
-		class TestOnFormIdentifierNotEmpty {
-
-			private final Optional<FormIdentifier> formIdentifier = Optional.of(FormIdentifierTestFactory.create());
-
-			@Test
-			void shouldReturnEmptyStream() {
-				var extracted = runner.extractBatchesOfDeletedVorgaengeFromDataSource(execution, formIdentifier);
-
-				assertThat(extracted).isEmpty();
-			}
-		}
-	}
-
-	@Nested
-	class TestGetPagedDeletedVorgaenge {
-
-		private static final int PAGE_SIZE = 2;
-
-		private final Stream<OzgCloudVorgangStub> vorgangStubs = Stream.generate(OzgCloudVorgangStubTestFactory::create).limit(PAGE_SIZE + 1);
-
 		@Test
-		void shouldReturnFirstFullPage() {
-			var pagingFunction = runner.getPagedDeletedVorgaenge(vorgangStubs);
-
-			var vorgaenge = getFirstPage(pagingFunction);
+		void shouldSetBatchSize() {
+			runner.prepareAggregator(execution, aggregationMapping);
 
-			assertThat(vorgaenge).hasSize(PAGE_SIZE);
+			verify(aggregator).withBatchSize(batchSize);
 		}
 
 		@Test
-		void shouldReturnSecondPageWithOneElement() {
-			var pagingFunction = runner.getPagedDeletedVorgaenge(vorgangStubs);
-			getFirstPage(pagingFunction);
-
-			var vorgaenge = getSecondPage(pagingFunction);
-
-			assertThat(vorgaenge).hasSize(1);
-		}
+		void shouldReturnAggregator() {
+			var result = runner.prepareAggregator(execution, aggregationMapping);
 
-		private List<OzgCloudVorgang> getFirstPage(Function<Page, List<OzgCloudVorgang>> pagingFunction) {
-			return pagingFunction.apply(Page.builder().offset(0).limit(PAGE_SIZE).build());
-		}
-
-		private List<OzgCloudVorgang> getSecondPage(Function<Page, List<OzgCloudVorgang>> pagingFunction) {
-			return pagingFunction.apply(Page.builder().offset(PAGE_SIZE).limit(PAGE_SIZE).build());
+			assertThat(result).isEqualTo(aggregator);
 		}
 	}
 
-	@Nested
-	class TestExtractBatchesFromDataSource {
-
-		private static final int BATCH_SIZE = 2;
-		private static final List<OzgCloudVorgang> VORGAENGE_1 = List.of(OzgCloudVorgangTestFactory.create(), OzgCloudVorgangTestFactory.create());
-		private static final List<OzgCloudVorgang> VORGAENGE_2 = List.of(OzgCloudVorgangTestFactory.create());
-		private static final UUID BATCH_1_UUID = UUID.randomUUID();
-		private static final UUID BATCH_2_UUID = UUID.randomUUID();
-
-		@Mock
-		private Execution execution;
-		@Mock
-		private Function<Page, List<OzgCloudVorgang>> functionToRetrieveData;
-
-		@BeforeEach
-		void init() {
-			when(config.getFetchingBatchSize()).thenReturn(BATCH_SIZE);
-			when(functionToRetrieveData.apply(any())).thenReturn(VORGAENGE_1, VORGAENGE_2, List.of());
-			when(runner.createBatchUUID()).thenReturn(BATCH_1_UUID, BATCH_2_UUID);
-		}
-
-		@Test
-		void shouldCallFunctionToRetrieveDataForFirstPage() {
-			extractBatchesFromDataSource();
-
-			verify(functionToRetrieveData).apply(argThat(hasExpectedOffsetAndConfiguredLimit(0)));
-		}
-
-		@Test
-		void shouldCallFunctionToRetrieveDataForSecondPage() {
-			extractBatchesFromDataSource().toList();
-
-			verify(functionToRetrieveData).apply(argThat(hasExpectedOffsetAndConfiguredLimit(BATCH_SIZE)));
-		}
-
-		@Test
-		void shouldCallFunctionToRetrieveDataForThirdPage() {
-			extractBatchesFromDataSource().toList();
-
-			verify(functionToRetrieveData).apply(argThat(hasExpectedOffsetAndConfiguredLimit(BATCH_SIZE * 2)));
-		}
-
-		@Test
-		void shouldReturnBatches() {
-			var batches = extractBatchesFromDataSource().toList();
-
-			assertThat(batches).hasSize(2).usingRecursiveFieldByFieldElementComparator().containsExactly(
-					new Batch(execution, BATCH_1_UUID, Page.builder().offset(0).limit(BATCH_SIZE).build(), VORGAENGE_1),
-					new Batch(execution, BATCH_2_UUID, Page.builder().offset(BATCH_SIZE).limit(BATCH_SIZE).build(), VORGAENGE_2));
-		}
+	static class AggregationManagerRunnerImpl extends AggregationManagerRunner {
 
-		private ArgumentMatcher<Page> hasExpectedOffsetAndConfiguredLimit(int expectedOffset) {
-			return page -> page.getOffset() == expectedOffset && page.getLimit() == BATCH_SIZE;
+		public AggregationManagerRunnerImpl(AggregationManagerConfiguration config, TransformationProperties transformationProperties,
+				TransformationService transformationService) {
+			super(config, transformationProperties, transformationService);
 		}
 
-		private Stream<Batch> extractBatchesFromDataSource() {
-			return runner.extractBatchesFromDataSource(execution, functionToRetrieveData);
+		@Override
+		protected Aggregator createAggregator() {
+			return aggregator;
 		}
 	}
 }
diff --git a/src/test/java/de/ozgcloud/aggregation/AggregatorTest.java b/src/test/java/de/ozgcloud/aggregation/AggregatorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..2d66f74b8f51b0eb4abbd382b62aa780b98dce54
--- /dev/null
+++ b/src/test/java/de/ozgcloud/aggregation/AggregatorTest.java
@@ -0,0 +1,551 @@
+package de.ozgcloud.aggregation;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.UUID;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+import org.apache.commons.lang3.RandomUtils;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.ArgumentMatcher;
+import org.mockito.Captor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.springframework.test.util.ReflectionTestUtils;
+
+import de.ozgcloud.aggregation.AggregationManagerRunner.Execution;
+import de.ozgcloud.aggregation.Aggregator.Batch;
+import de.ozgcloud.aggregation.transformation.AggregationMapping;
+import de.ozgcloud.aggregation.transformation.AggregationMapping.FormIdentifier;
+import de.ozgcloud.aggregation.transformation.AggregationMappingTestFactory;
+import de.ozgcloud.aggregation.transformation.FormIdentifierTestFactory;
+import de.ozgcloud.aggregation.transformation.Transformation;
+import de.ozgcloud.aggregation.transformation.VorgangMapper;
+import de.ozgcloud.aggregation.warehouse.DocumentEntry;
+import de.ozgcloud.aggregation.warehouse.DocumentEntryTestFactory;
+import de.ozgcloud.aggregation.warehouse.WarehouseRepository;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgang;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangQuery;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangService;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangStub;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangStubTestFactory;
+import de.ozgcloud.apilib.vorgang.OzgCloudVorgangTestFactory;
+import de.ozgcloud.apilib.vorgang.Page;
+
+class AggregatorTest {
+
+	@InjectMocks
+	@Spy
+	private Aggregator aggregator;
+	@Mock
+	private Transformation transformation;
+	private final Execution execution = new Execution(transformation);
+	@Mock
+	private WarehouseRepository repository;
+	@Mock
+	private VorgangMapper vorgangMapper;
+	@Mock
+	private OzgCloudVorgangService vorgangService;
+
+	@Nested
+	class TestWithExecution {
+
+		@Test
+		void shouldReturnSelf() {
+			var result = aggregator.withExecution(execution);
+
+			assertThat(result).isSameAs(aggregator);
+		}
+
+		@Test
+		void shouldSetExecution() {
+			var result = aggregator.withExecution(execution);
+
+			assertThat(ReflectionTestUtils.getField(result, "execution")).isEqualTo(execution);
+		}
+	}
+
+	@Nested
+	class TestWithAggregationMapping {
+
+		@Nested
+		class TestOnNonNullAggregationMapping {
+
+			private final AggregationMapping aggregationMapping = AggregationMappingTestFactory.create();
+			private final FormIdentifier formIdentifier = AggregationMappingTestFactory.FORM_IDENTIFIER;
+			private final String collectionName = AggregationMappingTestFactory.NAME;
+
+			@Test
+			void shouldReturnSelf() {
+				var result = aggregator.withAggregationMapping(aggregationMapping);
+
+				assertThat(result).isSameAs(aggregator);
+			}
+
+			@Test
+			void shouldSetFormIdentifier() {
+				var result = aggregator.withAggregationMapping(aggregationMapping);
+
+				assertThat(ReflectionTestUtils.getField(result, "formIdentifier")).isEqualTo(formIdentifier);
+			}
+
+			@Test
+			void shouldSetCollectionName() {
+				var result = aggregator.withAggregationMapping(aggregationMapping);
+
+				assertThat(ReflectionTestUtils.getField(result, "collectionName")).isEqualTo(collectionName);
+			}
+		}
+
+		@Nested
+		class TestOnNullAggregationMapping {
+
+			@Test
+			void shouldReturnSelf() {
+				var result = aggregator.withAggregationMapping(null);
+
+				assertThat(result).isSameAs(aggregator);
+			}
+
+			@Test
+			void shouldNotSetFormIdentifier() {
+				var result = aggregator.withAggregationMapping(null);
+
+				assertThat(ReflectionTestUtils.getField(result, "formIdentifier")).isNull();
+			}
+
+			@Test
+			void shouldNotSetCollectionName() {
+				var result = aggregator.withAggregationMapping(null);
+
+				assertThat(ReflectionTestUtils.getField(result, "collectionName")).isEqualTo(DocumentEntry.COLLECTION);
+			}
+		}
+	}
+
+	@Nested
+	class TestWithBatchSize {
+
+		private final int batchSize = RandomUtils.insecure().randomInt();
+
+		@Test
+		void shouldReturnSelf() {
+			var result = aggregator.withBatchSize(batchSize);
+
+			assertThat(result).isSameAs(aggregator);
+		}
+
+		@Test
+		void shouldSetBatchSize() {
+			var result = aggregator.withBatchSize(batchSize);
+
+			assertThat(ReflectionTestUtils.getField(result, "batchSize")).isEqualTo(batchSize);
+		}
+	}
+
+	@Nested
+	class TestAggregate {
+		@Mock
+		private Batch batchOfVorgaenge;
+		@Mock
+		private Batch batchOfDeletedVorgaenge;
+		@Captor
+		private ArgumentCaptor<Stream<Batch>> batchStreamCaptor;
+
+		@BeforeEach
+		void setUp() {
+			doReturn(Stream.of(batchOfVorgaenge)).when(aggregator).extractBatchesOfVorgaengeFromDataSource();
+			doReturn(Stream.of(batchOfDeletedVorgaenge)).when(aggregator).extractBatchesOfDeletedVorgaengeFromDataSource();
+			doNothing().when(aggregator).loadVorgaengeIntoRepository(any());
+		}
+
+		@Test
+		void shouldExtractBatchesOfVorgaengeFromDataSource() {
+			aggregator.aggregate();
+
+			verify(aggregator).extractBatchesOfVorgaengeFromDataSource();
+		}
+
+		@Test
+		void shouldExtractBatchesOfDeletedVorgaengeFromDataSource() {
+			aggregator.aggregate();
+
+			verify(aggregator).extractBatchesOfDeletedVorgaengeFromDataSource();
+		}
+
+		@Test
+		void shouldLoadVorgaengeIntoRepository() {
+			aggregator.aggregate();
+
+			verify(aggregator).loadVorgaengeIntoRepository(batchStreamCaptor.capture());
+			assertThat(batchStreamCaptor.getValue()).containsExactly(batchOfVorgaenge, batchOfDeletedVorgaenge);
+		}
+	}
+
+	@Nested
+	class TestExtractBatchesOfVorgaengeFromDataSource {
+		@Captor
+		private ArgumentCaptor<Function<Page, List<OzgCloudVorgang>>> functionToRetrieveDataCaptor;
+		@Mock
+		private Batch batch;
+		@Mock
+		private Page page;
+
+		@BeforeEach
+		void init() {
+			doReturn(Stream.of(batch)).when(aggregator).extractBatchesFromDataSource(any());
+		}
+
+		@Test
+		void shouldExtractWithDataRetrievalFunction() {
+			doReturn(Collections.emptyList()).when(aggregator).getVorgaengeFromDataSource(any());
+
+			aggregator.extractBatchesOfVorgaengeFromDataSource();
+
+			verify(aggregator).extractBatchesFromDataSource(functionToRetrieveDataCaptor.capture());
+			functionToRetrieveDataCaptor.getValue().apply(page);
+			verify(aggregator).getVorgaengeFromDataSource(page);
+		}
+
+		@Test
+		void shouldReturnExtractedBatches() {
+			var extracted = aggregator.extractBatchesOfVorgaengeFromDataSource();
+
+			assertThat(extracted).containsExactly(batch);
+		}
+	}
+
+	@Nested
+	class TestGetVorgaengeFromDataSource {
+
+		private final Page page = Page.builder().offset(10).limit(2).build();
+		private final OzgCloudVorgangQuery query = OzgCloudVorgangQuery.builder().build();
+
+		@BeforeEach
+		void init() {
+			doReturn(query).when(aggregator).buildFindByFormEngineQuery();
+			when(vorgangService.find(any(), any())).thenReturn(List.of(OzgCloudVorgangStubTestFactory.create()));
+			when(vorgangService.getById(any())).thenReturn(OzgCloudVorgangTestFactory.create());
+		}
+
+		@Test
+		void shouldCallBuildFindByFormEngineQuery() {
+			getVorgaengeFromDataSource();
+
+			verify(aggregator).buildFindByFormEngineQuery();
+		}
+
+		@Test
+		void shouldCallVorgangService() {
+			getVorgaengeFromDataSource();
+
+			verify(vorgangService).find(query, page);
+		}
+
+		@Test
+		void shouldGetVorgangDetails() {
+			getVorgaengeFromDataSource();
+
+			verify(vorgangService).getById(OzgCloudVorgangTestFactory.ID);
+		}
+
+		@Test
+		void shouldReturnVorgangDetails() {
+			var vorgaenge = getVorgaengeFromDataSource();
+
+			assertThat(vorgaenge).usingRecursiveFieldByFieldElementComparator().containsExactly(OzgCloudVorgangTestFactory.create());
+		}
+
+		private List<OzgCloudVorgang> getVorgaengeFromDataSource() {
+			return aggregator.getVorgaengeFromDataSource(page);
+		}
+	}
+
+	@Nested
+	class TestBuildFindByFormEngineQuery {
+
+		@Nested
+		class TestOnFormIdentifierNull {
+
+			@Test
+			void shouldReturnFindAllQueryOnNullFormIdentifier() {
+				var query = aggregator.buildFindByFormEngineQuery();
+
+				assertThat(query).usingRecursiveComparison().isEqualTo(OzgCloudVorgangQuery.builder().build());
+			}
+		}
+
+		@Nested
+		class TestOnFormIdentifierNotNull {
+
+			private final AggregationMapping aggregationMapping = AggregationMappingTestFactory.create();
+
+			@BeforeEach
+			void init() {
+				aggregator = aggregator.withAggregationMapping(aggregationMapping);
+			}
+
+			@Test
+			void shouldSetFormIdInQuery() {
+				var query = aggregator.buildFindByFormEngineQuery();
+
+				assertThat(query.getForm()).get().extracting("formId").isEqualTo(FormIdentifierTestFactory.FORM_ID);
+			}
+
+			@Test
+			void shouldSetFormEngineNameInQuery() {
+				var query = aggregator.buildFindByFormEngineQuery();
+
+				assertThat(query.getForm()).get().extracting("formEngineName").isEqualTo(FormIdentifierTestFactory.FORM_ENGINE_NAME);
+			}
+		}
+	}
+
+	@Nested
+	class TestExtractBatchesOfDeletedVorgaengeFromDataSource {
+
+		@Mock
+		private Execution execution;
+		@Mock
+		private Function<Page, List<OzgCloudVorgang>> functionToRetrieveData;
+		private final List<OzgCloudVorgangStub> deletedVorgaenge = List.of(OzgCloudVorgangStubTestFactory.create());
+		@Captor
+		private ArgumentCaptor<Stream<OzgCloudVorgangStub>> deletedVorgaengeCaptor;
+		@Mock
+		private Batch batch;
+
+		@Nested
+		class TestOnFormIdentifierNull {
+
+			@BeforeEach
+			void init() {
+				when(vorgangService.findDeleted()).thenReturn(deletedVorgaenge.stream());
+				doReturn(functionToRetrieveData).when(aggregator).getPagedDeletedVorgaenge(any());
+				doReturn(Stream.of(batch)).when(aggregator).extractBatchesFromDataSource(any());
+			}
+
+			@Test
+			void shouldFindDeleted() {
+				aggregator.extractBatchesOfDeletedVorgaengeFromDataSource();
+
+				verify(vorgangService).findDeleted();
+			}
+
+			@Test
+			void shouldGetPagedDeletedVorgaenge() {
+				aggregator.extractBatchesOfDeletedVorgaengeFromDataSource();
+
+				verify(aggregator).getPagedDeletedVorgaenge(deletedVorgaengeCaptor.capture());
+				assertThat(deletedVorgaengeCaptor.getValue()).usingRecursiveFieldByFieldElementComparator()
+						.containsExactlyElementsOf(deletedVorgaenge);
+			}
+
+			@Test
+			void shouldExtractWithDataRetrievalFunction() {
+				aggregator.extractBatchesOfDeletedVorgaengeFromDataSource();
+
+				verify(aggregator).extractBatchesFromDataSource(functionToRetrieveData);
+			}
+
+			@Test
+			void shouldReturnExtractedBatches() {
+				var extracted = aggregator.extractBatchesOfDeletedVorgaengeFromDataSource();
+
+				assertThat(extracted).containsExactly(batch);
+			}
+		}
+
+		@Nested
+		class TestOnFormIdentifierNotNull {
+
+			private final AggregationMapping aggregationMapping = AggregationMappingTestFactory.create();
+
+			@BeforeEach
+			void init() {
+				aggregator = aggregator.withAggregationMapping(aggregationMapping);
+			}
+
+			@Test
+			void shouldNotFindDeleted() {
+				aggregator.extractBatchesOfDeletedVorgaengeFromDataSource();
+
+				verify(vorgangService, never()).findDeleted();
+			}
+
+			@Test
+			void shouldReturnEmptyStream() {
+				var extracted = aggregator.extractBatchesOfDeletedVorgaengeFromDataSource();
+
+				assertThat(extracted).isEmpty();
+			}
+		}
+	}
+
+	@Nested
+	class TestGetPagedDeletedVorgaenge {
+
+		private static final int PAGE_SIZE = 2;
+
+		private final Stream<OzgCloudVorgangStub> vorgangStubs = Stream.generate(OzgCloudVorgangStubTestFactory::create).limit(PAGE_SIZE + 1);
+
+		@Test
+		void shouldReturnFirstFullPage() {
+			var pagingFunction = aggregator.getPagedDeletedVorgaenge(vorgangStubs);
+
+			var vorgaenge = getFirstPage(pagingFunction);
+
+			assertThat(vorgaenge).hasSize(PAGE_SIZE);
+		}
+
+		@Test
+		void shouldReturnSecondPageWithOneElement() {
+			var pagingFunction = aggregator.getPagedDeletedVorgaenge(vorgangStubs);
+			getFirstPage(pagingFunction);
+
+			var vorgaenge = getSecondPage(pagingFunction);
+
+			assertThat(vorgaenge).hasSize(1);
+		}
+
+		private List<OzgCloudVorgang> getFirstPage(Function<Page, List<OzgCloudVorgang>> pagingFunction) {
+			return pagingFunction.apply(Page.builder().offset(0).limit(PAGE_SIZE).build());
+		}
+
+		private List<OzgCloudVorgang> getSecondPage(Function<Page, List<OzgCloudVorgang>> pagingFunction) {
+			return pagingFunction.apply(Page.builder().offset(PAGE_SIZE).limit(PAGE_SIZE).build());
+		}
+	}
+
+	@Nested
+	class TestExtractBatchesFromDataSource {
+
+		private static final int BATCH_SIZE = 2;
+		private static final List<OzgCloudVorgang> VORGAENGE_1 = List.of(OzgCloudVorgangTestFactory.create(), OzgCloudVorgangTestFactory.create());
+		private static final List<OzgCloudVorgang> VORGAENGE_2 = List.of(OzgCloudVorgangTestFactory.create());
+		private static final UUID BATCH_1_UUID = UUID.randomUUID();
+		private static final UUID BATCH_2_UUID = UUID.randomUUID();
+
+		@Mock
+		private Function<Page, List<OzgCloudVorgang>> functionToRetrieveData;
+
+		@SuppressWarnings("unchecked")
+		@BeforeEach
+		void init() {
+			aggregator = aggregator.withBatchSize(BATCH_SIZE).withExecution(execution);
+			when(functionToRetrieveData.apply(any())).thenReturn(VORGAENGE_1, VORGAENGE_2, Collections.emptyList());
+			when(aggregator.createBatchUUID()).thenReturn(BATCH_1_UUID, BATCH_2_UUID);
+		}
+
+		@Test
+		void shouldCallFunctionToRetrieveDataForFirstPage() {
+			extractBatchesFromDataSource();
+
+			verify(functionToRetrieveData).apply(argThat(hasExpectedOffsetAndConfiguredLimit(0)));
+		}
+
+		@Test
+		void shouldCallFunctionToRetrieveDataForSecondPage() {
+			extractBatchesFromDataSource().toList();
+
+			verify(functionToRetrieveData).apply(argThat(hasExpectedOffsetAndConfiguredLimit(BATCH_SIZE)));
+		}
+
+		@Test
+		void shouldCallFunctionToRetrieveDataForThirdPage() {
+			extractBatchesFromDataSource().toList();
+
+			verify(functionToRetrieveData).apply(argThat(hasExpectedOffsetAndConfiguredLimit(BATCH_SIZE * 2)));
+		}
+
+		@Test
+		void shouldReturnBatches() {
+			var batches = extractBatchesFromDataSource().toList();
+
+			assertThat(batches).hasSize(2).usingRecursiveFieldByFieldElementComparator().containsExactly(
+					new Batch(execution, BATCH_1_UUID, Page.builder().offset(0).limit(BATCH_SIZE).build(), VORGAENGE_1),
+					new Batch(execution, BATCH_2_UUID, Page.builder().offset(BATCH_SIZE).limit(BATCH_SIZE).build(), VORGAENGE_2));
+		}
+
+		private ArgumentMatcher<Page> hasExpectedOffsetAndConfiguredLimit(int expectedOffset) {
+			return page -> page.getOffset() == expectedOffset && page.getLimit() == BATCH_SIZE;
+		}
+
+		private Stream<Batch> extractBatchesFromDataSource() {
+			return aggregator.extractBatchesFromDataSource(functionToRetrieveData);
+		}
+	}
+
+	@Nested
+	class TestLoadVorgaengeIntoRepository {
+
+		@Mock
+		private Execution execution;
+		@Mock
+		private Batch batch;
+		private final DocumentEntry documentEntry = DocumentEntryTestFactory.create();
+		private final AggregationMapping aggregationMapping = AggregationMappingTestFactory.create();
+		@Captor
+		private ArgumentCaptor<List<DocumentEntry>> documentEntriesCaptor;
+
+		@BeforeEach
+		void init() {
+			aggregator = aggregator.withAggregationMapping(aggregationMapping);
+			doReturn(List.of(documentEntry)).when(aggregator).transformBatchToDocumentEntries(any());
+			doNothing().when(aggregator).loadDocumentEntriesIntoRepository(any());
+		}
+
+		@Test
+		void shouldDropCollection() {
+			loadVorgaengeIntoRepository();
+
+			verify(repository).clearCollection(AggregationMappingTestFactory.NAME);
+		}
+
+		@Test
+		void shouldTransform() {
+			loadVorgaengeIntoRepository();
+
+			verify(aggregator).transformBatchToDocumentEntries(batch);
+		}
+
+		@Test
+		void shouldLoadIntoRepository() {
+			loadVorgaengeIntoRepository();
+
+			verify(aggregator).loadDocumentEntriesIntoRepository(documentEntriesCaptor.capture());
+			assertThat(documentEntriesCaptor.getValue()).containsExactly(documentEntry);
+		}
+
+		private void loadVorgaengeIntoRepository() {
+			aggregator.loadVorgaengeIntoRepository(Stream.of(batch));
+		}
+	}
+
+	@Nested
+	class TestLoadDocumentEntriesIntoRepository {
+
+		private final List<DocumentEntry> documentEntries = List.of(DocumentEntryTestFactory.create());
+		private final AggregationMapping aggregationMapping = AggregationMappingTestFactory.create();
+
+		@BeforeEach
+		void init() {
+			aggregator = aggregator.withAggregationMapping(aggregationMapping);
+		}
+
+		@Test
+		void shouldSaveDocumentEntriesInCollection() {
+			aggregator.loadDocumentEntriesIntoRepository(documentEntries);
+
+			verify(repository).saveAllInCollection(documentEntries, AggregationMappingTestFactory.NAME);
+		}
+	}
+}
diff --git a/src/test/java/de/ozgcloud/aggregation/transformation/AggregationMappingTestFactory.java b/src/test/java/de/ozgcloud/aggregation/transformation/AggregationMappingTestFactory.java
index 4be105f1284cafaef138f184ae54625242ad50e5..44a5c25ce128edf4625a5b95ab27d772bb621c46 100644
--- a/src/test/java/de/ozgcloud/aggregation/transformation/AggregationMappingTestFactory.java
+++ b/src/test/java/de/ozgcloud/aggregation/transformation/AggregationMappingTestFactory.java
@@ -23,6 +23,8 @@
  */
 package de.ozgcloud.aggregation.transformation;
 
+import com.thedeanda.lorem.LoremIpsum;
+
 import de.ozgcloud.aggregation.transformation.AggregationMapping.AggregationMappingBuilder;
 import de.ozgcloud.aggregation.transformation.AggregationMapping.FieldMapping;
 import de.ozgcloud.aggregation.transformation.AggregationMapping.FormIdentifier;
@@ -31,6 +33,7 @@ public class AggregationMappingTestFactory {
 
 	public static final FormIdentifier FORM_IDENTIFIER = FormIdentifierTestFactory.create();
 	public static final FieldMapping MAPPING = FieldMappingTestFactory.create();
+	public static final String NAME = LoremIpsum.getInstance().getWords(1);
 
 	public static AggregationMapping create() {
 		return createBuilder().build();
@@ -39,6 +42,7 @@ public class AggregationMappingTestFactory {
 	public static AggregationMappingBuilder createBuilder() {
 		return AggregationMapping.builder()
 				.formIdentifier(FORM_IDENTIFIER)
-				.fieldMapping(MAPPING);
+				.fieldMapping(MAPPING)
+				.name(NAME);
 	}
 }
diff --git a/src/test/java/de/ozgcloud/aggregation/warehouse/CustomWarehouseRepositoryImplTest.java b/src/test/java/de/ozgcloud/aggregation/warehouse/CustomWarehouseRepositoryImplTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..194a372bc2330c39c339baab737c0bf879fba26e
--- /dev/null
+++ b/src/test/java/de/ozgcloud/aggregation/warehouse/CustomWarehouseRepositoryImplTest.java
@@ -0,0 +1,88 @@
+package de.ozgcloud.aggregation.warehouse;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.util.List;
+
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.springframework.data.mongodb.core.MongoTemplate;
+
+import com.thedeanda.lorem.LoremIpsum;
+
+class CustomWarehouseRepositoryImplTest {
+
+	@Spy
+	@InjectMocks
+	private CustomWarehouseRepositoryImpl repository;
+
+	@Mock
+	private MongoTemplate mongoTemplate;
+
+	@Nested
+	class TestSaveAllInCollection {
+
+		private final DocumentEntry documentEntry = DocumentEntryTestFactory.create();
+		private final List<DocumentEntry> documentEntries = List.of(documentEntry);
+		private final String collectionName = LoremIpsum.getInstance().getWords(1);
+
+		@Test
+		void shouldCallSaveInCollection() {
+			repository.saveAllInCollection(documentEntries, collectionName);
+
+			verify(repository).saveInCollection(documentEntry, collectionName);
+		}
+
+		@Test
+		void shouldReturnSavedDocumentEntry() {
+			var savedDocumentEntry = DocumentEntryTestFactory.create();
+			doReturn(savedDocumentEntry).when(repository).saveInCollection(any(), any());
+
+			var returnedDocumentEntries = repository.saveAllInCollection(documentEntries, collectionName);
+
+			assertThat(returnedDocumentEntries).containsExactly(savedDocumentEntry);
+		}
+	}
+
+	@Nested
+	class TestSaveInCollection {
+
+		private final DocumentEntry documentEntry = DocumentEntryTestFactory.create();
+		private final String collectionName = LoremIpsum.getInstance().getWords(1);
+
+		@Test
+		void testSaveInCollection() {
+			repository.saveInCollection(documentEntry, collectionName);
+
+			verify(mongoTemplate).save(documentEntry, collectionName);
+		}
+
+		@Test
+		void shouldReturnSavedDocumentEntry() {
+			var savedDocumentEntry = DocumentEntryTestFactory.create();
+			when(mongoTemplate.save(documentEntry, collectionName)).thenReturn(savedDocumentEntry);
+
+			var returnedDocumentEntry = repository.saveInCollection(documentEntry, collectionName);
+
+			assertThat(returnedDocumentEntry).isEqualTo(savedDocumentEntry);
+		}
+	}
+
+	@Nested
+	class TestDeleteCollection {
+
+		private final String collectionName = LoremIpsum.getInstance().getWords(1);
+
+		@Test
+		void shouldDropCollection() {
+			repository.clearCollection(collectionName);
+
+			verify(mongoTemplate).dropCollection(collectionName);
+		}
+	}
+}
diff --git a/src/test/java/de/ozgcloud/aggregation/warehouse/WarehouseRepositoryITCase.java b/src/test/java/de/ozgcloud/aggregation/warehouse/WarehouseRepositoryITCase.java
index 18a3ab40118388b784fee2bfe17873ae5ec811d7..ad1c860d0f6006f1c13a5ca3cf5c349863bf136d 100644
--- a/src/test/java/de/ozgcloud/aggregation/warehouse/WarehouseRepositoryITCase.java
+++ b/src/test/java/de/ozgcloud/aggregation/warehouse/WarehouseRepositoryITCase.java
@@ -32,6 +32,8 @@ import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.mongodb.core.MongoOperations;
 
+import com.thedeanda.lorem.LoremIpsum;
+
 import de.ozgcloud.common.test.DataITCase;
 
 @DataITCase
@@ -57,7 +59,33 @@ class WarehouseRepositoryITCase {
 			var foundDocument = mongoOperations.findById(savedDocument.getId(), Document.class, DocumentEntry.COLLECTION);
 			assertThat(foundDocument.getString("_class")).isEqualTo("Vorgang");
 		}
+	}
+
+	@Nested
+	class TestSaveInCollection {
 
+		private final String collectionName = LoremIpsum.getInstance().getWords(1);
+
+		@Test
+		void shouldSaveInCollection() {
+			repository.saveInCollection(DocumentEntryTestFactory.create(), collectionName);
+
+			assertThat(mongoOperations.getCollection(collectionName).countDocuments()).isOne();
+		}
 	}
 
+	@Nested
+	class TestClearCollection {
+
+		private final String collectionName = LoremIpsum.getInstance().getWords(1);
+
+		@Test
+		void shouldClearCollection() {
+			mongoOperations.save(DocumentEntryTestFactory.create(), collectionName);
+
+			repository.clearCollection(collectionName);
+
+			assertThat(mongoOperations.getCollection(collectionName).countDocuments()).isZero();
+		}
+	}
 }