diff --git a/common/src/test/java/de/ozgcloud/eingang/common/formdata/FormDataTestFactory.java b/common/src/test/java/de/ozgcloud/eingang/common/formdata/FormDataTestFactory.java
index 52dcddeaf62afa188e0716294bf84d615eb5c945..100eefcfe1c6629650fcaaca896ccdabc973a84c 100644
--- a/common/src/test/java/de/ozgcloud/eingang/common/formdata/FormDataTestFactory.java
+++ b/common/src/test/java/de/ozgcloud/eingang/common/formdata/FormDataTestFactory.java
@@ -53,6 +53,10 @@ public class FormDataTestFactory {
 
 	public static final String VORGANG_ID = "vorgangId";
 
+	public static final List<IncomingFileGroup> ATTACHMENTS = List.of(IncomingFileGroupTestFactory.create(),
+			IncomingFileGroupTestFactory.createBuilder().name(ATTACHMENT_GROUP_2).build());
+	public static final List<IncomingFile> REPRESENTATIONS = List.of(IncomingFileTestFactory.create());
+
 	public static FormData create() {
 		return createBuilder().build();
 	}
@@ -72,10 +76,9 @@ public class FormDataTestFactory {
 				.numberOfAttachments(2)
 				// TODO zweites Attachment aus der TestFactory entfernen und die entsprechenden
 				// Tests anpassen
-				.attachments(List.of(IncomingFileGroupTestFactory.create(),
-						IncomingFileGroupTestFactory.createBuilder().name(ATTACHMENT_GROUP_2).build()))
+				.attachments(ATTACHMENTS)
 				.numberOfRepresentations(1)
-				.representations(List.of(IncomingFileTestFactory.create()));
+				.representations(REPRESENTATIONS);
 	}
 
 	@SafeVarargs
diff --git a/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimDataMapper.java b/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimDataMapper.java
index 84ea086db65f80050e41f253694a1c674f017285..86b2f8738e84035d602e577756f98ffaa41cfe21 100644
--- a/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimDataMapper.java
+++ b/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimDataMapper.java
@@ -2,14 +2,12 @@ package de.ozgcloud.eingang.fim;
 
 import java.util.LinkedHashMap;
 import java.util.Map;
-import java.util.Optional;
 
 import org.apache.commons.lang3.function.TriFunction;
 import org.springframework.stereotype.Service;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
 import org.w3c.dom.Text;
 
 import de.ozgcloud.eingang.common.formdata.FormData;
@@ -17,46 +15,61 @@ import lombok.extern.log4j.Log4j2;
 
 @Service
 @Log4j2
-class FimDataMapper implements TriFunction<Document, FimScheme, FormData, FormData.FormDataBuilder> {
-
-    private static final String LABEL_KEY = "label";
-    private static final String VALUE_KEY = "value";
-
-    @Override
-    public FormData.FormDataBuilder apply(final Document document, final FimScheme fimScheme, final FormData initialFormData) {
-        final FormData.FormDataBuilder formDataBuilder = FormData.builder();
-        Map<String, Object> data = new LinkedHashMap<>();
-        process(document.getDocumentElement(), fimScheme, data, 0);
-        formDataBuilder.formData(data);
-        formDataBuilder.attachments(initialFormData.getAttachments());
-        formDataBuilder.representations(initialFormData.getRepresentations());
-        return formDataBuilder;
-    }
-
-    private void process(final Element element, final FimScheme fimScheme, final Map<String, Object> data, final int level) {
-        final NodeList childNodes = element.getChildNodes();
-
-        LOG.debug(">".repeat(level) + " " + element.getNodeName());
-
-        for(int i = 0; i < childNodes.getLength();i++) {
-            final Node child = childNodes.item(i);
-            if (!(child instanceof Element)) {
-                continue;
-            }
-            if (child.getChildNodes().getLength() == 1 && child.getChildNodes().item(0) instanceof Text textNode) {
-                insertValueIntoFormData(data, fimScheme.getFieldName(child.getNodeName()), child.getNodeName(), textNode.getTextContent());
-            } else {
-                final Map<String, Object> childMap = new LinkedHashMap<>();
-                insertValueIntoFormData(data, fimScheme.getFieldName(child.getNodeName()), child.getNodeName(), childMap);
-                process((Element) child, fimScheme, childMap, level + 1);
-            }
-        }
-    }
-
-    private void insertValueIntoFormData(final Map<String, Object> data, final Optional<String> fieldName, final String nodeName, final Object obj) {
-        final String[] fieldNameParts = nodeName.split(":");
-        final String fieldNameWithoutNamespace = fieldNameParts[fieldNameParts.length - 1];
-        final Map<String, Object> labelMap = Map.of(LABEL_KEY, fieldName.orElse(fieldNameWithoutNamespace), VALUE_KEY, obj);
-        data.put(fieldNameWithoutNamespace, labelMap);
-    }
+class FimDataMapper implements TriFunction<Document, FimScheme, FormData, FormData> {
+
+	private static final String LABEL_KEY = "label";
+	private static final String VALUE_KEY = "value";
+
+	@Override
+	public FormData apply(Document document, FimScheme fimScheme, FormData initialFormData) {
+		return FormData.builder()
+				.formData(extractDocumentData(document.getDocumentElement(), fimScheme))
+				.attachments(initialFormData.getAttachments())
+				.representations(initialFormData.getRepresentations())
+				.build();
+	}
+
+	Map<String, Object> extractDocumentData(Element documentRoot, FimScheme fimScheme) {
+		var data = new LinkedHashMap<String, Object>();
+		processNode(documentRoot, fimScheme, data, 0);
+		return data;
+	}
+
+	void processNode(Node element, FimScheme fimScheme, Map<String, Object> data, int level) {
+		LOG.debug(">".repeat(level) + " " + element.getNodeName());
+
+		var childNodes = element.getChildNodes();
+		for (int i = 0; i < childNodes.getLength(); i++) {
+			if (childNodes.item(i) instanceof Element childElement) {
+				processElement(childElement, fimScheme, data, level);
+			}
+		}
+	}
+
+	void processElement(Element childElement, FimScheme fimScheme, Map<String, Object> data, int level) {
+		var fieldName = fimScheme.getFieldName(childElement.getNodeName());
+		var fieldNameWithoutNamespace = getFieldNameWithoutNamespace(childElement.getNodeName());
+		var label = fieldName.orElse(fieldNameWithoutNamespace);
+
+		if (isTextNode(childElement)) {
+			data.put(fieldNameWithoutNamespace, buildFieldMap(label, childElement.getTextContent()));
+		} else {
+			var childMap = new LinkedHashMap<String, Object>();
+			data.put(fieldNameWithoutNamespace, buildFieldMap(label, childMap));
+			processNode(childElement, fimScheme, childMap, level + 1);
+		}
+	}
+
+	private String getFieldNameWithoutNamespace(String nodeName) {
+		var fieldNameParts = nodeName.split(":");
+		return fieldNameParts[fieldNameParts.length - 1];
+	}
+
+	private boolean isTextNode(Node child) {
+		return child.getChildNodes().getLength() == 1 && child.getChildNodes().item(0) instanceof Text;
+	}
+
+	private Map<String, Object> buildFieldMap(String fieldName, Object obj) {
+		return Map.<String, Object>of(LABEL_KEY, fieldName, VALUE_KEY, obj);
+	}
 }
diff --git a/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimDataUtil.java b/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimDataUtil.java
index f21f185c5b6365174c2eb7ab2169b64f007e9b6e..ca6e3716e8bd54ab9676c7aed71205e0fd294bc1 100644
--- a/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimDataUtil.java
+++ b/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimDataUtil.java
@@ -1,35 +1,40 @@
 package de.ozgcloud.eingang.fim;
 
-import org.apache.commons.lang3.ArrayUtils;
-
 import java.util.Map;
 import java.util.Optional;
 
-public class FimDataUtil {
+import org.apache.commons.lang3.ArrayUtils;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+class FimDataUtil {
+
+	public static Map<String, Object> getSubmap(Map<String, Object> data, String... path) {
+		var current = data;
+		for (final String step : path) {
+			current = map(current, step);
+		}
+		return current;
+	}
 
-    public static Map<String, Object> getSubmap(final Map<String, Object> data, final String... path) {
-        Map<String, Object> current = data;
-        for (final String step : path) {
-            current = map(current, step);
-        }
-        return current;
-    }
-    public static Optional<String> getValue(final Map<String, Object> data, final String... path) {
-        Map<String, Object> current = getSubmap(data, ArrayUtils.subarray(path, 0, path.length - 1));
-        if (current == null) {
-            return Optional.empty();
-        }
-        return Optional.ofNullable((String)((Map<String, Object>) current.get(path[path.length - 1])).get("value"));
-    }
+	public static Optional<String> getValue(final Map<String, Object> data, String... path) {
+		var current = getSubmap(data, ArrayUtils.subarray(path, 0, path.length - 1));
+		if (current == null) {
+			return Optional.empty();
+		}
+		return Optional.ofNullable((String) ((Map<String, Object>) current.get(path[path.length - 1])).get("value"));
+	}
 
-    private static Map<String, Object> map(Map<String, Object> obj, String key) {
-        if (obj == null) {
-            return null;
-        }
-        final Object data = obj.get(key);
-        if (!(data instanceof Map)) {
-            return null;
-        }
-        return (Map<String, Object>)((Map<String, Object>) data).get("value");
-    }
+	private static Map<String, Object> map(Map<String, Object> obj, String key) {
+		if (obj == null) {
+			return null;
+		}
+		var data = obj.get(key);
+		if (!(data instanceof Map)) {
+			return null;
+		}
+		return (Map<String, Object>) ((Map<String, Object>) data).get("value");
+	}
 }
diff --git a/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimService.java b/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimService.java
index 381cb4e04896e27ae780605187fc041ebdd943e0..adfaeaecd74b248202dce577ef437a71bd5038a7 100644
--- a/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimService.java
+++ b/fim-adapter/src/main/java/de/ozgcloud/eingang/fim/FimService.java
@@ -24,8 +24,8 @@ import de.ozgcloud.eingang.common.formdata.FormHeader;
 import io.micrometer.common.util.StringUtils;
 import lombok.extern.log4j.Log4j2;
 
-@Service
 @Log4j2
+@Service
 public class FimService {
 	public static final String UNKNOWN_SCHEME_NAME = "unknown";
 
@@ -89,17 +89,16 @@ public class FimService {
 			throw new FimException("XML Document does not provide a scheme");
 		}
 		final FimScheme scheme = getSchemeForIdentifier(schemeName);
-		final FormData.FormDataBuilder builder = fimDataMapper.apply(document, scheme, initialFormData);
-
-		builder.header(initialFormData.getHeader());
+		var formData = fimDataMapper.apply(document, scheme, initialFormData);
 
-		extractAntragsteller(builder, initialFormData);
-		extractVorgangsname(builder, initialFormData);
-
-		return builder.build();
+		return formData.toBuilder()
+				.header(initialFormData.getHeader())
+				.antragsteller(buildAntragsteller(formData))
+				.header(buildFormHeader(formData))
+				.build();
 	}
 
-	FimScheme getSchemeForIdentifier(final String fimSchemaName) {
+	FimScheme getSchemeForIdentifier(String fimSchemaName) {
 		final FimSchemeIdentifier fimSchemeIdentifier = FimSchemeIdentifier.fromString(fimSchemaName);
 		final FimScheme fimScheme = fimSchemeCatalogue.get(fimSchemeIdentifier);
 		if (fimScheme == null) {
@@ -109,12 +108,12 @@ public class FimService {
 		return fimScheme;
 	}
 
-	private void extractAntragsteller(final FormData.FormDataBuilder builder, final FormData initialFormData) {
-		final FormData current = builder.build();
-		final Map<String, Object> anzeigenErsteller = FimDataUtil.getSubmap(current.getFormData(), "G17002112");
-		final Map<String, Object> anschrift = FimDataUtil.getSubmap(anzeigenErsteller, "G60000086");
+	// THINKME In Mapper auslagern
+	private Antragsteller buildAntragsteller(FormData formData) {
+		var anzeigenErsteller = getAnzeigenErsteller(formData);
+		var anschrift = getAnschrift(anzeigenErsteller);
 
-		Antragsteller antragsteller = Antragsteller.builder()
+		return Antragsteller.builder()
 				.vorname(FimDataUtil.getValue(anzeigenErsteller, "F60000228").orElse(null))
 				.nachname(FimDataUtil.getValue(anzeigenErsteller, "F60000227").orElse(null))
 				.email(FimDataUtil.getValue(anzeigenErsteller, "F60000242").orElse(null))
@@ -122,18 +121,25 @@ public class FimService {
 				.hausnummer(FimDataUtil.getValue(anschrift, "F60000244").orElse(null))
 				.plz(FimDataUtil.getValue(anschrift, "F60000246").orElse(null))
 				.ort(FimDataUtil.getValue(anschrift, "F60000247").orElse(null))
-
 				.build();
-		builder.antragsteller(antragsteller);
 	}
 
-	private void extractVorgangsname(final FormData.FormDataBuilder builder, final FormData initialFormData) {
-		final FormData current = builder.build();
-		final Optional<String> vorgangsname = FimDataUtil.getValue(current.getFormData(), "G17003529", "G05001479", "G05001480", "F05002753");
+	// ASKME AnzeigenErsteller ?!
+	private Map<String, Object> getAnzeigenErsteller(FormData formData) {
+		return FimDataUtil.getSubmap(formData.getFormData(), "G17002112");
+	}
+
+	private Map<String, Object> getAnschrift(Map<String, Object> anzeigenErsteller) {
+		return FimDataUtil.getSubmap(anzeigenErsteller, "G60000086");
+	}
 
-		final FormHeader.FormHeaderBuilder headerBuilder = current.getHeader().toBuilder();
+	private FormHeader buildFormHeader(FormData formData) {
+		return formData.getHeader().toBuilder()
+				.formName(getVorgangsName(formData).orElse(null))
+				.build();
+	}
 
-		headerBuilder.formName(vorgangsname.orElse(null));
-		builder.header(headerBuilder.build());
+	private Optional<String> getVorgangsName(FormData formData) {
+		return FimDataUtil.getValue(formData.getFormData(), "G17003529", "G05001479", "G05001480", "F05002753");
 	}
 }
\ No newline at end of file
diff --git a/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/FimDataMapperTest.java b/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/FimDataMapperTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..3a53dd9665d2678c5f1dc49e87817453704240b3
--- /dev/null
+++ b/fim-adapter/src/test/java/de/ozgcloud/eingang/fim/FimDataMapperTest.java
@@ -0,0 +1,117 @@
+package de.ozgcloud.eingang.fim;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.*;
+
+import java.util.Map;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+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.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import de.ozgcloud.eingang.common.formdata.FormData;
+import de.ozgcloud.eingang.common.formdata.FormDataTestFactory;
+
+class FimDataMapperTest {
+
+	@Spy
+	@InjectMocks
+	private FimDataMapper mapper;
+
+	@DisplayName("Apply")
+	@Nested
+	class TestApply {
+
+		@Mock
+		private Document document;
+		@Mock
+		private Element element;
+		@Mock
+		private FimScheme fimScheme;
+		@Mock
+		private Map<String, Object> extractedDocumentData;
+
+		private final FormData formData = FormDataTestFactory.create();
+
+		@BeforeEach
+		void mock() {
+			when(document.getDocumentElement()).thenReturn(element);
+
+			doReturn(extractedDocumentData).when(mapper).extractDocumentData(any(), any());
+		}
+
+		@Test
+		void shouldCallExtractDocumentData() {
+			apply();
+
+			verify(mapper).extractDocumentData(element, fimScheme);
+		}
+
+		@Test
+		void shouldPutExtractDocumentDataInFormData() {
+			var appliedFormData = apply();
+
+			assertThat(appliedFormData.getFormData()).isEqualTo(extractedDocumentData);
+		}
+
+		@Test
+		void shouldKeepAttachmentsInFormData() {
+			var appliedFormData = apply();
+
+			assertThat(appliedFormData.getAttachments()).isEqualTo(FormDataTestFactory.ATTACHMENTS);
+		}
+
+		@Test
+		void shouldKeepRepresentationsInFormData() {
+			var appliedFormData = apply();
+
+			assertThat(appliedFormData.getRepresentations()).isEqualTo(FormDataTestFactory.REPRESENTATIONS);
+		}
+
+		private FormData apply() {
+			return mapper.apply(document, fimScheme, formData);
+		}
+	}
+
+	@DisplayName("Extract document data")
+	@Nested
+	class TestExtractDocumentData {
+
+		@Mock
+		private Element root;
+		@Mock
+		private FimScheme fimScheme;
+
+		@BeforeEach
+		void mock() {
+			doNothing().when(mapper).processNode(any(), any(), any(), anyInt());
+		}
+
+		@Test
+		void shouldCallProcessElement() {
+			mapper.extractDocumentData(root, fimScheme);
+
+			verify(mapper).processNode(eq(root), eq(fimScheme), any(), eq(0));
+		}
+
+		@Test
+		void shouldReturnCreatedMap() {
+			var dataMap = mapper.extractDocumentData(root, fimScheme);
+
+			assertThat(dataMap).isNotNull();
+		}
+	}
+
+	@DisplayName("Process element")
+	@Nested
+	class TestProcessElement {
+
+	}
+}
\ No newline at end of file