diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/Lock.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/Lock.java
index a888e0ea88582596dc39af16e2007bc66a507c3e..336a0335d93e27f781b0e1e119f9adbd383cdbe6 100644
--- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/Lock.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/Lock.java
@@ -25,19 +25,23 @@ package de.ozgcloud.vorgang.vorgang;
 
 import java.time.ZonedDateTime;
 
+import jakarta.validation.constraints.NotNull;
 import lombok.Builder;
 import lombok.Getter;
 
 @Builder
 @Getter
-class Lock {
+public class Lock {
 
 	static final String FIELD_CLIENT_NAME = "clientName";
 	static final String FIELD_LOCKED_SINCE = "lockedSince";
 	static final String FIELD_REASON = "reason";
 
+	@NotNull
 	private final String clientName;
+	@NotNull
 	private final ZonedDateTime lockedSince;
+	@NotNull
 	private final String reason;
 
 }
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/LockMapper.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/LockMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..c94e7b76508223828c076c1873e39386a1972a99
--- /dev/null
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/LockMapper.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2025 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.vorgang;
+
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.util.Map;
+
+import org.apache.commons.collections.MapUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+
+import de.ozgcloud.command.Command;
+
+@Mapper
+interface LockMapper {
+
+	@Mapping(target = "clientName", source = "createdByClientName")
+	@Mapping(target = "lockedSince", expression = "java(getLockedSince())")
+	@Mapping(target = "reason", source = "bodyObject")
+	Lock fromCommand(Command command);
+
+	default String getReason(Map<String, Object> bodyObject) {
+		return StringUtils.trimToNull(MapUtils.getString(bodyObject, Lock.FIELD_REASON));
+	}
+
+	default ZonedDateTime getLockedSince() {
+		return ZonedDateTime.now(ZoneId.of("UTC"));
+	}
+}
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangEventListener.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangEventListener.java
index be036bb8112e61cf4047e4591806ea13caf39282..d44544422fb18c593bf381db34cd515b612f116d 100644
--- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangEventListener.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangEventListener.java
@@ -37,6 +37,7 @@ import de.ozgcloud.command.CommandFailedEvent;
 import de.ozgcloud.command.CommandRevokeFailedEvent;
 import de.ozgcloud.command.CommandRevokedEvent;
 import de.ozgcloud.command.RevokeCommandEvent;
+import de.ozgcloud.command.VorgangLockedEvent;
 import de.ozgcloud.command.VorgangUnlockedEvent;
 import de.ozgcloud.vorgang.command.CommandService;
 import de.ozgcloud.vorgang.command.Order;
@@ -72,6 +73,7 @@ public class VorgangEventListener {
 	private final VorgangHeaderService vorgangHeaderService;
 	private final FileService fileService;
 	private final CommandService commandService;
+	private final LockMapper lockMapper;
 
 	private final ApplicationEventPublisher publisher;
 
@@ -122,7 +124,8 @@ public class VorgangEventListener {
 	public void onLockVorgang(CommandCreatedEvent event) {
 		var command = event.getSource();
 		try {
-			vorgangService.lockVorgang(command);
+			vorgangService.lockVorgang(lockMapper.fromCommand(command), command.getVorgangId(), command.getRelationVersion());
+			publisher.publishEvent(new VorgangLockedEvent(command));
 		} catch (RuntimeException e) {
 			LOG.error("Error locking vorgang.", e);
 			publisher.publishEvent(new CommandFailedEvent(command.getId(), e.getMessage()));
diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangService.java
index 3cbc342a0f46aad3c4131a1d2033996f0d372eb2..a4690f4c7a4ebc99ea5aaa2a25ce0b4d8f7b28a0 100644
--- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangService.java
+++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/vorgang/VorgangService.java
@@ -23,13 +23,10 @@
  */
 package de.ozgcloud.vorgang.vorgang;
 
-import java.time.ZoneId;
-import java.time.ZonedDateTime;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
-import java.util.Objects;
 import java.util.Optional;
 import java.util.stream.Stream;
 
@@ -44,8 +41,6 @@ import org.springframework.validation.annotation.Validated;
 import de.ozgcloud.command.Command;
 import de.ozgcloud.command.VorgangAssignedEvent;
 import de.ozgcloud.command.VorgangCreatedEvent;
-import de.ozgcloud.command.VorgangLockedEvent;
-import de.ozgcloud.common.errorhandling.TechnicalException;
 import de.ozgcloud.vorgang.clientattribute.ClientAttributeMap;
 import de.ozgcloud.vorgang.clientattribute.ClientAttributeReadPermitted;
 import de.ozgcloud.vorgang.clientattribute.ClientAttributesMap;
@@ -223,30 +218,15 @@ public class VorgangService {
 		return repository.findById(vorgangId).orElseThrow(() -> new NotFoundException(Vorgang.class, vorgangId));
 	}
 
-	public void lockVorgang(Command command) {
-		validateLockCommand(command);
-		repository.patch(command.getVorgangId(), command.getRelationVersion(), buildLockPatch(command));
-		publisher.publishEvent(new VorgangLockedEvent(command));
+	public void lockVorgang(@Valid Lock lock, String vorgangId, Long version) {
+		repository.patch(vorgangId, version, buildLockPatch(lock));
 	}
 
-	void validateLockCommand(Command command) {
-		if (Objects.isNull(command.getCreatedByClientName())) {
-			throw new TechnicalException("Missing client name in lock command");
-		}
-		if (Objects.isNull(getReason(command.getBodyObject()))) {
-			throw new TechnicalException("Missing reason in lock command");
-		}
-	}
-
-	Map<String, Object> buildLockPatch(Command command) {
+	Map<String, Object> buildLockPatch(Lock lock) {
 		return Map.of(KEY_HEADER_LOCK, Map.of(
-				Lock.FIELD_CLIENT_NAME, command.getCreatedByClientName(),
-				Lock.FIELD_LOCKED_SINCE, ZonedDateTime.now(ZoneId.of("UTC")),
-				Lock.FIELD_REASON, getReason(command.getBodyObject())));
-	}
-
-	String getReason(Map<String, Object> commandBody) {
-		return StringUtils.trimToNull(MapUtils.getString(commandBody, Lock.FIELD_REASON));
+				Lock.FIELD_CLIENT_NAME, lock.getClientName(),
+				Lock.FIELD_LOCKED_SINCE, lock.getLockedSince(),
+				Lock.FIELD_REASON, lock.getReason()));
 	}
 
 	public boolean isVorgangLocked(String vorgangId) {
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/LockMapperTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/LockMapperTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..990b9432410674f86f32c3e2e2558fa0f31d4d43
--- /dev/null
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/LockMapperTest.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2025 Das Land Schleswig-Holstein vertreten durch den
+ * Ministerpräsidenten des Landes Schleswig-Holstein
+ * Staatskanzlei
+ * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
+ *
+ * Lizenziert unter der EUPL, Version 1.2 oder - sobald
+ * diese von der Europäischen Kommission genehmigt wurden -
+ * Folgeversionen der EUPL ("Lizenz");
+ * Sie dürfen dieses Werk ausschließlich gemäß
+ * dieser Lizenz nutzen.
+ * Eine Kopie der Lizenz finden Sie hier:
+ *
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Sofern nicht durch anwendbare Rechtsvorschriften
+ * gefordert oder in schriftlicher Form vereinbart, wird
+ * die unter der Lizenz verbreitete Software "so wie sie
+ * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
+ * ausdrücklich oder stillschweigend - verbreitet.
+ * Die sprachspezifischen Genehmigungen und Beschränkungen
+ * unter der Lizenz sind dem Lizenztext zu entnehmen.
+ */
+package de.ozgcloud.vorgang.vorgang;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.temporal.ChronoUnit;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.NullAndEmptySource;
+import org.junit.jupiter.params.provider.ValueSource;
+import org.mapstruct.factory.Mappers;
+import org.mockito.Spy;
+
+import com.thedeanda.lorem.LoremIpsum;
+
+import de.ozgcloud.command.Command;
+import de.ozgcloud.vorgang.command.CommandTestFactory;
+
+class LockMapperTest {
+
+	@Spy
+	private LockMapper mapper = Mappers.getMapper(LockMapper.class);
+
+	@Nested
+	class TestFromCommand {
+
+		private final Command command = CommandTestFactory.createBuilder().bodyObject(Map.of(Lock.FIELD_REASON, LockTestFactory.REASON)).build();
+
+		@BeforeEach
+		void init() {
+			doReturn(LockTestFactory.REASON).when(mapper).getReason(any());
+			doReturn(LockTestFactory.LOCKED_SINCE).when(mapper).getLockedSince();
+		}
+
+		@Test
+		void shouldGetLockedSince() {
+			map();
+
+			verify(mapper).getLockedSince();
+		}
+
+		@Test
+		void shouldGetReason() {
+			map();
+
+			verify(mapper).getReason(command.getBodyObject());
+		}
+
+		@Test
+		void shouldMap() {
+			var mapped = map();
+
+			assertThat(mapped).usingRecursiveComparison().isEqualTo(LockTestFactory.create());
+		}
+
+		private Lock map() {
+			return mapper.fromCommand(command);
+		}
+	}
+
+	@Nested
+	class TestGetReason {
+
+		@Test
+		void shouldReturnNullIfKeyNotFound() {
+			var mapped = mapper.getReason(Map.of("dummyKey", "dummyValue"));
+
+			assertThat(mapped).isNull();
+		}
+
+		@Test
+		void shouldReturnNullIfValueIsNull() {
+			Map<String, Object> bodyObject = new HashMap<>();
+			bodyObject.put(Lock.FIELD_REASON, null); // need to put, because Map.of() does not accept null values
+
+			var mapped = mapper.getReason(bodyObject);
+
+			assertThat(mapped).isNull();
+		}
+
+		@Test
+		void shouldReturnReason() {
+			var reason = LoremIpsum.getInstance().getWords(2);
+			Map<String, Object> bodyObject = Map.of(Lock.FIELD_REASON, reason);
+
+			var mapped = mapper.getReason(bodyObject);
+
+			assertThat(mapped).isEqualTo(reason);
+		}
+
+		@ParameterizedTest
+		@ValueSource(strings = { " " })
+		@NullAndEmptySource
+		void shouldTrimToNull(String reason) {
+			Map<String, Object> bodyObject = new HashMap<>();
+			bodyObject.put(Lock.FIELD_REASON, reason); // need to put, because Map.of() does not accept null values
+
+			var mapped = mapper.getReason(bodyObject);
+
+			assertThat(mapped).isNull();
+		}
+	}
+
+	@Nested
+	class TestLockedSince {
+
+		@Test
+		void shouldReturnCurrentTime() {
+			var lockedSince = mapper.getLockedSince();
+
+			assertThat(lockedSince).isCloseTo(ZonedDateTime.now(ZoneId.of("UTC")), within(2, ChronoUnit.SECONDS));
+		}
+	}
+}
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangEventListenerTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangEventListenerTest.java
index d8bb400c4d00f2573bbc4a922e3991d1155ada24..dc3152d7860268d0c1554f4bdfb1127363718722 100644
--- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangEventListenerTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangEventListenerTest.java
@@ -50,6 +50,7 @@ import de.ozgcloud.command.CommandFailedEvent;
 import de.ozgcloud.command.CommandRevokeFailedEvent;
 import de.ozgcloud.command.CommandRevokedEvent;
 import de.ozgcloud.command.RevokeCommandEvent;
+import de.ozgcloud.command.VorgangLockedEvent;
 import de.ozgcloud.command.VorgangUnlockedEvent;
 import de.ozgcloud.common.errorhandling.TechnicalException;
 import de.ozgcloud.vorgang.command.CommandCreatedEventTestFactory;
@@ -77,6 +78,8 @@ class VorgangEventListenerTest {
 	private FileService fileService;
 	@Mock
 	private CommandService commandService;
+	@Mock
+	private LockMapper lockMapper;
 
 	@Mock
 	private ApplicationEventPublisher publisher;
@@ -239,32 +242,66 @@ class VorgangEventListenerTest {
 	@Nested
 	class TestOnLockVorgang {
 
+		private final Command command = CommandTestFactory.create();
+		private final Lock lock = LockTestFactory.create();
 		@Captor
-		private ArgumentCaptor<CommandFailedEvent> eventCaptor;
+		private ArgumentCaptor<VorgangLockedEvent> lockedEventCaptor;
+		@Captor
+		private ArgumentCaptor<CommandFailedEvent> failedEventCaptor;
+
+		@BeforeEach
+		void init() {
+			when(lockMapper.fromCommand(any())).thenReturn(lock);
+		}
+
+		@Test
+		void shouldMapToLock() {
+			onLockVorgang();
+
+			verify(lockMapper).fromCommand(command);
+		}
 
 		@Test
 		void shouldCallLockVorgang() {
-			var command = CommandTestFactory.create();
+			onLockVorgang();
 
-			listener.onLockVorgang(CommandCreatedEventTestFactory.create(command));
+			verify(service).lockVorgang(lock, VorgangTestFactory.ID, CommandTestFactory.RELATION_VERSION);
+		}
+
+		@Test
+		void shouldCallPublishEvent() {
+			onLockVorgang();
 
-			verify(service).lockVorgang(command);
+			verify(publisher).publishEvent(lockedEventCaptor.capture());
+			assertThat(lockedEventCaptor.getValue().getCommand()).isSameAs(command);
 		}
 
 		@Test
 		void shouldPublishCommandFailedEvent() {
-			var command = CommandTestFactory.create();
 			var errorMessage = "error message";
-			doThrow(new RuntimeException(errorMessage)).when(service).lockVorgang(command);
+			doThrow(new RuntimeException(errorMessage)).when(service).lockVorgang(any(), any(), anyLong());
 
-			listener.onLockVorgang(CommandCreatedEventTestFactory.create(command));
+			onLockVorgang();
 
-			verify(publisher).publishEvent(eventCaptor.capture());
-			assertThat(eventCaptor.getValue()).satisfies(event -> {
+			verify(publisher).publishEvent(failedEventCaptor.capture());
+			assertThat(failedEventCaptor.getValue()).satisfies(event -> {
 				assertThat(event.getSource()).isEqualTo(CommandTestFactory.ID);
 				assertThat(event.getErrorMessage()).isEqualTo(errorMessage);
 			});
 		}
+
+		@Test
+		void shouldNotPublishVorgangLockedEventOnFailure() {
+			doThrow(new RuntimeException("error message")).when(service).lockVorgang(any(), any(), anyLong());
+
+			onLockVorgang();
+
+			verify(publisher, never()).publishEvent(any(VorgangLockedEvent.class));
+		}
+
+		private void onLockVorgang() {
+			listener.onLockVorgang(CommandCreatedEventTestFactory.create(command));
+		}
 	}
 
 	@Nested
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangServiceITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangServiceITCase.java
index 1ddb4dee4a51eee8accad0ed3cf06c913228bddf..f4a60955119cc46ea93b5add821b0d91533c3c1b 100644
--- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangServiceITCase.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangServiceITCase.java
@@ -29,20 +29,19 @@ import static org.mockito.Mockito.*;
 
 import java.util.List;
 
-import jakarta.validation.ConstraintViolationException;
-
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.mock.mockito.MockBean;
 import org.springframework.security.test.context.support.WithMockUser;
+import org.springframework.test.context.bean.override.mockito.MockitoBean;
 
 import de.ozgcloud.common.test.DataITCase;
 import de.ozgcloud.notification.antragsteller.AntragstellerNotificationEventListener;
 import de.ozgcloud.notification.user.UserNotificationEventListener;
 import de.ozgcloud.vorgang.command.CommandService;
 import de.ozgcloud.vorgang.servicekonto.ServiceKontoTestFactory;
+import jakarta.validation.ConstraintViolationException;
 
 @DataITCase
 @WithMockUser
@@ -51,14 +50,14 @@ class VorgangServiceITCase {
 	@Autowired
 	private VorgangService vorgangService;
 
-	@MockBean
+	@MockitoBean
 	private CommandService commandService;
-
-	@MockBean
+	@MockitoBean
 	private AntragstellerNotificationEventListener antragstellerNotificationEventListener;
-
-	@MockBean
+	@MockitoBean
 	private UserNotificationEventListener userNotificationEventListener;
+	@MockitoBean
+	private VorgangRepository vorgangRepository;
 
 	@DisplayName("Test creating a new Vorgang")
 	@Nested
@@ -92,11 +91,49 @@ class VorgangServiceITCase {
 			@Test
 			void shouldBeInvalidOnMissingPostfachAddress() {
 				var eingang = EingangTestFactory.createBuilder().header(EingangHeaderTestFactory.createBuilder()
-						.serviceKonto(ServiceKontoTestFactory.createBuilder().clearPostfachAddresses().build()).build())
+								.serviceKonto(ServiceKontoTestFactory.createBuilder().clearPostfachAddresses().build()).build())
 						.build();
 
 				assertThatThrownBy(() -> vorgangService.startCreation(eingang)).isInstanceOf(ConstraintViolationException.class);
 			}
 		}
 	}
+
+	@Nested
+	class TestLockVorgang {
+
+		@Nested
+		class TestValidation {
+
+			@Test
+			void shouldBeInvalidOnMissingClientName() {
+				var lock = LockTestFactory.createBuilder().clientName(null).build();
+
+				assertThatThrownBy(() -> vorgangService.lockVorgang(lock, VorgangTestFactory.ID, VorgangTestFactory.VERSION)).isInstanceOf(
+						ConstraintViolationException.class);
+			}
+
+			@Test
+			void shouldBeInvalidOnMissingLockedSince() {
+				var lock = LockTestFactory.createBuilder().lockedSince(null).build();
+
+				assertThatThrownBy(() -> vorgangService.lockVorgang(lock, VorgangTestFactory.ID, VorgangTestFactory.VERSION)).isInstanceOf(
+						ConstraintViolationException.class);
+			}
+
+			@Test
+			void shouldBeInvalidOnMissingReason() {
+				var lock = LockTestFactory.createBuilder().reason(null).build();
+
+				assertThatThrownBy(() -> vorgangService.lockVorgang(lock, VorgangTestFactory.ID, VorgangTestFactory.VERSION)).isInstanceOf(
+						ConstraintViolationException.class);
+			}
+
+			@Test
+			void shouldBeValidWhenRequiredFieldsAreNotNull() {
+				assertThatNoException().isThrownBy(
+						() -> vorgangService.lockVorgang(LockTestFactory.create(), VorgangTestFactory.ID, VorgangTestFactory.VERSION));
+			}
+		}
+	}
 }
\ No newline at end of file
diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangServiceTest.java
index 3449659b130bca698edbf9b3b88daf73fe867efc..dd60f6033b802cfcf4909ad46d8420ee73119dad 100644
--- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangServiceTest.java
+++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/vorgang/VorgangServiceTest.java
@@ -28,13 +28,10 @@ import static org.junit.jupiter.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
-import java.time.ZonedDateTime;
-import java.time.temporal.ChronoUnit;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 
-import org.assertj.core.api.*;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
@@ -53,7 +50,6 @@ import de.ozgcloud.command.Command;
 import de.ozgcloud.command.VorgangAssignedEvent;
 import de.ozgcloud.command.VorgangCreatedEvent;
 import de.ozgcloud.command.VorgangLockedEvent;
-import de.ozgcloud.common.errorhandling.TechnicalException;
 import de.ozgcloud.vorgang.clientattribute.ClientAttributeReadPermitted;
 import de.ozgcloud.vorgang.command.CommandTestFactory;
 import de.ozgcloud.vorgang.common.errorhandling.NotFoundException;
@@ -352,7 +348,8 @@ class VorgangServiceTest {
 			void shouldThrowAccessDeniedException() {
 				when(vorgangAuthorizationService.authorizeByOrganisationseinheitenId(any(), any())).thenReturn(false);
 
-				assertThrows(AccessDeniedException.class, () -> service.getById(VorgangTestFactory.ID, FilterCriteriaTestFactory.create())); // NOSONAR
+				assertThrows(AccessDeniedException.class,
+						() -> service.getById(VorgangTestFactory.ID, FilterCriteriaTestFactory.create())); // NOSONAR
 			}
 		}
 
@@ -516,7 +513,7 @@ class VorgangServiceTest {
 	@Nested
 	class TestLockVorgang {
 
-		private static final Command LOCK_COMMAND = CommandTestFactory.create();
+		private final Lock lock = LockTestFactory.create();
 		private static final Map<String, Object> LOCK_PATCH = Map.of("key", "value");
 
 		@Captor
@@ -524,92 +521,53 @@ class VorgangServiceTest {
 
 		@BeforeEach
 		void init() {
-			doNothing().when(service).validateLockCommand(any());
 			doReturn(LOCK_PATCH).when(service).buildLockPatch(any());
 		}
 
-		@Test
-		void shouldCallValidateLockCommand() {
-			service.lockVorgang(LOCK_COMMAND);
-
-			verify(service).validateLockCommand(LOCK_COMMAND);
-		}
-
 		@Test
 		void shouldCallBuildLockPatch() {
-			service.lockVorgang(LOCK_COMMAND);
+			lockVorgang();
 
-			verify(service).buildLockPatch(LOCK_COMMAND);
+			verify(service).buildLockPatch(lock);
 		}
 
 		@Test
 		void shouldCallRepository() {
-			service.lockVorgang(LOCK_COMMAND);
+			lockVorgang();
 
 			verify(repository).patch(VorgangTestFactory.ID, CommandTestFactory.RELATION_VERSION, LOCK_PATCH);
 		}
 
-		@Test
-		void shouldCallPublishEvent() {
-			service.lockVorgang(LOCK_COMMAND);
-
-			verify(publisher).publishEvent(eventCaptor.capture());
-			assertThat(eventCaptor.getValue().getCommand()).isSameAs(LOCK_COMMAND);
-		}
-	}
-
-	@Nested
-	class TestValidateLockCommand {
-
-		@Test
-		void shouldThrowExceptionOnMissingClient() {
-			var command = CommandTestFactory.createBuilder().createdByClientName(null).build();
-
-			assertThrows(TechnicalException.class, () -> service.validateLockCommand(command));
-		}
-
-		@Test
-		void shouldThrowExceptionOnMissingReason() {
-			var command = CommandTestFactory.createBuilder().bodyObject(Map.of()).build();
-
-			assertThrows(TechnicalException.class, () -> service.validateLockCommand(command));
-		}
-
-		@Test
-		void shouldAcceptValidCommand() {
-			var command = CommandTestFactory.createBuilder().bodyObject(Map.of(Lock.FIELD_REASON, LockTestFactory.REASON)).build();
-
-			assertDoesNotThrow(() -> service.validateLockCommand(command));
+		private void lockVorgang() {
+			service.lockVorgang(lock, VorgangTestFactory.ID, VorgangTestFactory.VERSION);
 		}
 	}
 
 	@Nested
 	class TestBuildLockPatch {
 
-		private final Command command = CommandTestFactory.createBuilder().bodyObject(Map.of(Lock.FIELD_REASON, LockTestFactory.REASON)).build();
-
 		@Test
 		void shouldSetClientName() {
-			var result = service.buildLockPatch(command);
+			var result = service.buildLockPatch(LockTestFactory.create());
 
 			assertThat(result).extractingByKey(VorgangService.KEY_HEADER_LOCK, MAP)
-					.containsEntry(Lock.FIELD_CLIENT_NAME, CommandTestFactory.CREATED_BY_CLIENT);
+					.containsEntry(Lock.FIELD_CLIENT_NAME, LockTestFactory.CLIENT_NAME);
 		}
 
 		@Test
 		void shouldSetLockedSince() {
-			var result = service.buildLockPatch(command);
+			var result = service.buildLockPatch(LockTestFactory.create());
 
 			assertThat(result).extractingByKey(VorgangService.KEY_HEADER_LOCK, MAP)
-					.extractingByKey(Lock.FIELD_LOCKED_SINCE, InstanceOfAssertFactories.ZONED_DATE_TIME)
-					.isCloseTo(ZonedDateTime.now(), within(1, ChronoUnit.SECONDS));
+					.containsEntry(Lock.FIELD_LOCKED_SINCE, LockTestFactory.LOCKED_SINCE);
 		}
 
 		@Test
 		void shouldSetReason() {
-			var result = service.buildLockPatch(command);
+			var result = service.buildLockPatch(LockTestFactory.create());
 
-			assertThat(result).extractingByKey(VorgangService.KEY_HEADER_LOCK, MAP).containsEntry(Lock.FIELD_REASON, LockTestFactory.REASON);
+			assertThat(result).extractingByKey(VorgangService.KEY_HEADER_LOCK, MAP)
+					.containsEntry(Lock.FIELD_REASON, LockTestFactory.REASON);
 		}
 	}
 
@@ -760,7 +718,6 @@ class VorgangServiceTest {
 		}
 	}
 
-
 	@Nested
 	class TestFindDeleted {