diff --git a/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/service/DataCiteIdentifierServiceUnitTest.java b/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/service/DataCiteIdentifierServiceUnitTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..9e1ad3736e4a8545e52557d9163ce9634c8ee6cf
--- /dev/null
+++ b/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/service/DataCiteIdentifierServiceUnitTest.java
@@ -0,0 +1,227 @@
+package at.tuwien.service;
+
+import at.tuwien.BaseUnitTest;
+import at.tuwien.api.identifier.IdentifierCreateDto;
+import at.tuwien.api.identifier.IdentifierDto;
+import at.tuwien.config.DataCiteConfig;
+import at.tuwien.config.EndpointConfig;
+import at.tuwien.config.IndexInitializer;
+import at.tuwien.datacite.DataCiteBody;
+import at.tuwien.datacite.DataCiteData;
+import at.tuwien.datacite.doi.DataCiteDoi;
+import at.tuwien.entities.identifier.Identifier;
+import at.tuwien.exception.*;
+import at.tuwien.repository.jpa.ContainerRepository;
+import at.tuwien.repository.jpa.DatabaseRepository;
+import at.tuwien.repository.jpa.IdentifierRepository;
+import at.tuwien.repository.jpa.ImageRepository;
+import at.tuwien.service.impl.IdentifierServiceImpl;
+import org.apache.http.auth.BasicUserPrincipal;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Answers;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.boot.web.client.RestTemplateBuilder;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.springframework.web.client.HttpClientErrorException;
+import org.springframework.web.client.RestClientException;
+import org.springframework.web.client.RestTemplate;
+
+import java.security.Principal;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(SpringExtension.class)
+@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
+@SpringBootTest
+@ActiveProfiles("doi")
+public class DataCiteIdentifierServiceUnitTest extends BaseUnitTest {
+
+    @MockBean
+    private IndexInitializer indexInitializer;
+
+    @MockBean(answer = Answers.RETURNS_MOCKS)
+    private DataCiteConfig dataCiteConfig;
+
+    @MockBean(answer = Answers.RETURNS_MOCKS)
+    private EndpointConfig endpointConfig;
+
+    @Autowired
+    private ImageRepository imageRepository;
+
+    @Autowired
+    private ContainerRepository containerRepository;
+
+    @Autowired
+    private DatabaseRepository databaseRepository;
+
+    @Autowired
+    private IdentifierRepository identifierRepository;
+
+    @MockBean
+    private RestTemplate restTemplate;
+
+    @MockBean(answer = Answers.RETURNS_SELF)
+    private RestTemplateBuilder restTemplateBuilder;
+
+    @MockBean
+    private IdentifierServiceImpl identifierService;
+
+    @Autowired
+    private IdentifierService dataCiteIdentifierService;
+
+    @BeforeEach
+    public void beforeEach() {
+        imageRepository.save(IMAGE_1);
+        containerRepository.save(CONTAINER_1);
+        databaseRepository.save(DATABASE_1);
+        when(restTemplateBuilder.build()).thenReturn(restTemplate);
+        IDENTIFIER_1.setCreators(null);
+    }
+
+    @Test
+    public void create_database_succeeds()
+            throws DatabaseNotFoundException, UserNotFoundException, IdentifierAlreadyExistsException,
+            QueryNotFoundException, IdentifierPublishingNotAllowedException, RemoteUnavailableException,
+            IdentifierRequestException {
+        final Principal principal = new BasicUserPrincipal(USER_1_USERNAME);
+        final String bearer = "Bearer abcxyz";
+        final String doi = "10.000/thisisadoi";
+        final DataCiteBody<DataCiteDoi> response =
+                new DataCiteBody<>(new DataCiteData<>(null, "dois", new DataCiteDoi(doi)));
+
+        /* mock */
+        when(identifierService.create(any(IdentifierCreateDto.class), eq(principal), eq(bearer)))
+                .thenAnswer((i) -> identifierRepository.save(IDENTIFIER_1));
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class),
+                any(ParameterizedTypeReference.class)))
+                .thenReturn(ResponseEntity.status(HttpStatus.CREATED).body(response));
+
+        /* test */
+        Identifier result = dataCiteIdentifierService.create(IDENTIFIER_1_DTO_REQUEST, principal, bearer);
+        assertTrue(identifierRepository.existsById(result.getId()));
+        assertEquals(doi, result.getDoi());
+    }
+
+    @Test
+    public void create_invalidMetadata_fails()
+            throws IdentifierAlreadyExistsException, UserNotFoundException, QueryNotFoundException,
+            DatabaseNotFoundException, RemoteUnavailableException, IdentifierPublishingNotAllowedException,
+            IdentifierRequestException {
+        final Principal principal = new BasicUserPrincipal(USER_1_USERNAME);
+        final String bearer = "Bearer abcxyz";
+
+        /* mock */
+        when(identifierService.create(any(IdentifierCreateDto.class), eq(principal), eq(bearer)))
+                .thenAnswer((i) -> identifierRepository.save(IDENTIFIER_1));
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class),
+                any(ParameterizedTypeReference.class)))
+                .thenThrow(HttpClientErrorException.BadRequest.class);
+
+        /* test */
+        assertThrows(IdentifierRequestException.class, () -> {
+            dataCiteIdentifierService.create(IDENTIFIER_1_DTO_REQUEST, principal, bearer);
+        });
+        assertEquals(0, identifierRepository.count());
+    }
+
+    @Test
+    public void create_restClientException_fails()
+            throws IdentifierAlreadyExistsException, UserNotFoundException, QueryNotFoundException,
+            DatabaseNotFoundException, RemoteUnavailableException, IdentifierPublishingNotAllowedException,
+            IdentifierRequestException {
+        final Principal principal = new BasicUserPrincipal(USER_1_USERNAME);
+        final String bearer = "Bearer abcxyz";
+
+        /* mock */
+        when(identifierService.create(any(IdentifierCreateDto.class), eq(principal), eq(bearer)))
+                .thenAnswer((i) -> identifierRepository.save(IDENTIFIER_1));
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class),
+                any(ParameterizedTypeReference.class)))
+                .thenThrow(RestClientException.class);
+
+        /* test */
+        assertThrows(InternalError.class, () -> {
+            dataCiteIdentifierService.create(IDENTIFIER_1_DTO_REQUEST, principal, bearer);
+        });
+        assertEquals(0, identifierRepository.count());
+    }
+
+    @Test
+    public void update_existing_succeeds()
+            throws IdentifierRequestException, IdentifierNotFoundException {
+        final String doi = "10.000/thisisanotherdoi";
+        final DataCiteBody<DataCiteDoi> response =
+                new DataCiteBody<>(new DataCiteData<>(null, "dois", new DataCiteDoi(doi)));
+        IDENTIFIER_1.setDoi(doi);
+
+        /* mock */
+        when(identifierService.update(eq(IDENTIFIER_1_ID), any(IdentifierDto.class)))
+                .thenAnswer((i) -> identifierRepository.save(IDENTIFIER_1));
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class),
+                any(ParameterizedTypeReference.class), eq(doi)))
+                .thenReturn(ResponseEntity.ok(response));
+
+        /* test */
+        Identifier result = dataCiteIdentifierService.update(IDENTIFIER_1_ID, IDENTIFIER_1_DTO);
+        assertTrue(identifierRepository.existsById(IDENTIFIER_1_ID));
+        assertEquals(doi, result.getDoi());
+    }
+
+    @Test
+    public void update_invalidMetadata_fails()
+            throws IdentifierRequestException, IdentifierNotFoundException {
+        final String doi = "10.000/thisisanotherdoi";
+        final DataCiteBody<DataCiteDoi> response =
+                new DataCiteBody<>(new DataCiteData<>(null, "dois", new DataCiteDoi(doi)));
+        IDENTIFIER_1.setDoi(doi);
+
+        /* mock */
+        when(identifierService.update(eq(IDENTIFIER_1_ID), any(IdentifierDto.class)))
+                .thenAnswer((i) -> identifierRepository.save(IDENTIFIER_1));
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class),
+                any(ParameterizedTypeReference.class), eq(doi)))
+                .thenThrow(HttpClientErrorException.BadRequest.class);
+
+        /* test */
+        assertThrows(IdentifierRequestException.class, () -> {
+            dataCiteIdentifierService.update(IDENTIFIER_1_ID, IDENTIFIER_1_DTO);
+        });
+        assertEquals(0, identifierRepository.count());
+    }
+
+    @Test
+    public void update_restClientException_fails()
+            throws IdentifierRequestException, IdentifierNotFoundException {
+        final String doi = "10.000/thisisanotherdoi";
+        final DataCiteBody<DataCiteDoi> response =
+                new DataCiteBody<>(new DataCiteData<>(null, "dois", new DataCiteDoi(doi)));
+        IDENTIFIER_1.setDoi(doi);
+
+        /* mock */
+        when(identifierService.update(eq(IDENTIFIER_1_ID), any(IdentifierDto.class)))
+                .thenAnswer((i) -> identifierRepository.save(IDENTIFIER_1));
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class),
+                any(ParameterizedTypeReference.class), eq(doi)))
+                .thenThrow(RestClientException.class);
+
+        /* test */
+        assertThrows(InternalError.class, () -> {
+            dataCiteIdentifierService.update(IDENTIFIER_1_ID, IDENTIFIER_1_DTO);
+        });
+        assertEquals(0, identifierRepository.count());
+    }
+
+}
diff --git a/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/service/IdentifierServiceUnitTest.java b/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/service/IdentifierServiceUnitTest.java
index 80cc3fb52586c7375e113b8b20c0734d62c7ca95..0e4315bbf2dc6105ac90ea0b4b5b1e75cec74fdc 100644
--- a/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/service/IdentifierServiceUnitTest.java
+++ b/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/service/IdentifierServiceUnitTest.java
@@ -3,6 +3,7 @@ package at.tuwien.service;
 import at.tuwien.BaseUnitTest;
 import at.tuwien.api.database.query.QueryDto;
 import at.tuwien.api.identifier.IdentifierDto;
+import at.tuwien.api.identifier.VisibilityTypeDto;
 import at.tuwien.config.IndexInitializer;
 import at.tuwien.entities.identifier.Identifier;
 import at.tuwien.entities.identifier.IdentifierType;
@@ -186,6 +187,39 @@ public class IdentifierServiceUnitTest extends BaseUnitTest {
         });
     }
 
+    @Test
+    public void update_doiChange_fails() {
+
+        Identifier identifier = Identifier.builder().id(IDENTIFIER_1_ID).doi("10.000/thisisadoi").build();
+        IdentifierDto identifierDto = IdentifierDto.builder().id(IDENTIFIER_1_ID).visibility(VisibilityTypeDto.EVERYONE).doi("10.000/thisisadifferentdoi").build();
+
+        /* mock */
+        when(identifierRepository.findById(IDENTIFIER_1_ID))
+                .thenReturn(Optional.of(identifier));
+
+        /* test */
+        assertThrows(IdentifierRequestException.class, () -> {
+            identifierService.update(IDENTIFIER_1_ID, identifierDto);
+        });
+    }
+
+    @Test
+    public void update_notVisibleByEveryone_fails() {
+
+        Identifier identifier = Identifier.builder().id(IDENTIFIER_1_ID).build();
+        IdentifierDto identifierDto = IdentifierDto.builder().id(IDENTIFIER_1_ID).visibility(VisibilityTypeDto.TRUSTED).build();
+        IDENTIFIER_1_DTO.setVisibility(VisibilityTypeDto.TRUSTED);
+
+        /* mock */
+        when(identifierRepository.findById(IDENTIFIER_1_ID))
+                .thenReturn(Optional.of(identifier));
+
+        /* test */
+        assertThrows(IdentifierRequestException.class, () -> {
+            identifierService.update(IDENTIFIER_1_ID, identifierDto);
+        });
+    }
+
     @Test
     public void create_database_succeeds()
             throws DatabaseNotFoundException, UserNotFoundException, IdentifierAlreadyExistsException,
@@ -282,6 +316,24 @@ public class IdentifierServiceUnitTest extends BaseUnitTest {
         });
     }
 
+    @Test
+    public void delete_withDoi_fails() {
+
+        Identifier identifier = Identifier.builder().id(IDENTIFIER_1_ID).doi("10.000/thisisadoi").build();
+
+        /* mock */
+        when(identifierRepository.findById(IDENTIFIER_1_ID))
+                .thenReturn(Optional.of(identifier));
+        doNothing()
+                .when(identifierRepository)
+                .delete(IDENTIFIER_1);
+
+        /* test */
+        assertThrows(NotAllowedException.class, () -> {
+            identifierService.delete(IDENTIFIER_1_ID);
+        });
+    }
+
     @Test
     public void exportMetadata_succeeds() throws IdentifierNotFoundException {