From 80fad43e7a4905fa506d23f6fd7fa16ba8437b6a Mon Sep 17 00:00:00 2001
From: Martin Weise <martin.weise@tuwien.ac.at>
Date: Wed, 16 Nov 2022 21:55:35 +0100
Subject: [PATCH] Fixed tests for container service

---
 .../src/test/java/at/tuwien/BaseUnitTest.java |  52 ++++
 .../java/at/tuwien/config/SecurityConfig.java |  39 +++
 .../endpoint/ContainerEndpointUnitTest.java   | 262 +++++-------------
 .../ContainerServiceIntegrationTest.java      |   2 -
 .../resources/docker/inspect_running.json     | 251 +++++++++++++++++
 5 files changed, 412 insertions(+), 194 deletions(-)
 create mode 100644 fda-container-service/rest-service/src/test/java/at/tuwien/config/SecurityConfig.java
 create mode 100644 fda-container-service/rest-service/src/test/resources/docker/inspect_running.json

diff --git a/fda-container-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java b/fda-container-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java
index 2797e45b87..394cfd2d8c 100644
--- a/fda-container-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java
+++ b/fda-container-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java
@@ -8,6 +8,8 @@ import at.tuwien.entities.container.image.ContainerImageEnvironmentItem;
 import at.tuwien.entities.container.image.ContainerImageEnvironmentItemType;
 import at.tuwien.entities.user.RoleType;
 import at.tuwien.entities.user.User;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
 import org.springframework.test.context.TestPropertySource;
 
 import java.time.Instant;
@@ -24,6 +26,7 @@ public abstract class BaseUnitTest {
     public final static Boolean USER_1_THEME_DARK = false;
     public final static String USER_1_PASSWORD = "p455w0rdh45h";
     public final static RoleType USER_1_ROLE_TYPE = RoleType.ROLE_RESEARCHER;
+    public final static GrantedAuthority USER_1_AUTHORITY = new SimpleGrantedAuthority("ROLE_RESEARCHER");
 
     public final static User USER_1 = User.builder()
             .username(USER_1_USERNAME)
@@ -34,6 +37,55 @@ public abstract class BaseUnitTest {
             .roles(List.of(USER_1_ROLE_TYPE))
             .build();
 
+    public final static String USER_2_USERNAME = "dev";
+    public final static String USER_2_EMAIL = "dev@gmail.com";
+    public final static Boolean USER_2_EMAIL_VERIFIED = false;
+    public final static Boolean USER_2_THEME_DARK = false;
+    public final static String USER_2_PASSWORD = "p455w0rdh45";
+    public final static RoleType USER_2_ROLE_TYPE = RoleType.ROLE_DEVELOPER;
+    public final static GrantedAuthority USER_2_AUTHORITY = new SimpleGrantedAuthority("ROLE_DEVELOPER");
+
+    public final static User USER_2 = User.builder()
+            .username(USER_2_USERNAME)
+            .email(USER_2_EMAIL)
+            .emailVerified(USER_2_EMAIL_VERIFIED)
+            .themeDark(USER_2_THEME_DARK)
+            .password(USER_2_PASSWORD)
+            .roles(List.of(USER_2_ROLE_TYPE))
+            .build();
+
+    public final static String USER_3_USERNAME = "steward";
+    public final static String USER_3_EMAIL = "steward@gmail.com";
+    public final static Boolean USER_3_EMAIL_VERIFIED = false;
+    public final static Boolean USER_3_THEME_DARK = false;
+    public final static String USER_3_PASSWORD = "p455w0rdh45";
+    public final static RoleType USER_3_ROLE_TYPE = RoleType.ROLE_DATA_STEWARD;
+    public final static GrantedAuthority USER_3_AUTHORITY = new SimpleGrantedAuthority("ROLE_DATA_STEWARD");
+
+    public final static User USER_3 = User.builder()
+            .username(USER_3_USERNAME)
+            .email(USER_3_EMAIL)
+            .emailVerified(USER_3_EMAIL_VERIFIED)
+            .themeDark(USER_3_THEME_DARK)
+            .password(USER_3_PASSWORD)
+            .roles(List.of(USER_3_ROLE_TYPE))
+            .build();
+
+    public final static String USER_4_USERNAME = "nobody";
+    public final static String USER_4_EMAIL = "nobody@gmail.com";
+    public final static Boolean USER_4_EMAIL_VERIFIED = false;
+    public final static Boolean USER_4_THEME_DARK = false;
+    public final static String USER_4_PASSWORD = "p455w0rdh45";
+
+    public final static User USER_4 = User.builder()
+            .username(USER_4_USERNAME)
+            .email(USER_4_EMAIL)
+            .emailVerified(USER_4_EMAIL_VERIFIED)
+            .themeDark(USER_4_THEME_DARK)
+            .password(USER_4_PASSWORD)
+            .roles(List.of())
+            .build();
+
     public final static Long IMAGE_1_ID = 1L;
     public final static String IMAGE_1_REPOSITORY = "mariadb";
     public final static String IMAGE_1_TAG = "10.5";
diff --git a/fda-container-service/rest-service/src/test/java/at/tuwien/config/SecurityConfig.java b/fda-container-service/rest-service/src/test/java/at/tuwien/config/SecurityConfig.java
new file mode 100644
index 0000000000..532304a61b
--- /dev/null
+++ b/fda-container-service/rest-service/src/test/java/at/tuwien/config/SecurityConfig.java
@@ -0,0 +1,39 @@
+package at.tuwien.config;
+
+import at.tuwien.BaseUnitTest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.provisioning.InMemoryUserDetailsManager;
+
+import java.util.List;
+
+@Configuration
+public class SecurityConfig extends BaseUnitTest {
+
+    @Autowired
+    private PasswordEncoder passwordEncoder;
+
+    @Bean
+    public PasswordEncoder passwordEncoder() {
+        return new BCryptPasswordEncoder();
+    }
+
+    @Bean
+    public UserDetailsService userDetailsService() {
+        return new InMemoryUserDetailsManager(List.of(
+                new User(USER_1_USERNAME, passwordEncoder.encode(USER_1_PASSWORD), List.of(USER_1_AUTHORITY)),
+                new User(USER_2_USERNAME, passwordEncoder.encode(USER_2_PASSWORD), List.of(USER_2_AUTHORITY)),
+                new User(USER_3_USERNAME, passwordEncoder.encode(USER_3_PASSWORD), List.of(USER_3_AUTHORITY)),
+                new User(USER_4_USERNAME, passwordEncoder.encode(USER_4_PASSWORD), List.of())
+        ));
+    }
+
+}
diff --git a/fda-container-service/rest-service/src/test/java/at/tuwien/endpoint/ContainerEndpointUnitTest.java b/fda-container-service/rest-service/src/test/java/at/tuwien/endpoint/ContainerEndpointUnitTest.java
index c2a05be2b9..eb17402c9d 100644
--- a/fda-container-service/rest-service/src/test/java/at/tuwien/endpoint/ContainerEndpointUnitTest.java
+++ b/fda-container-service/rest-service/src/test/java/at/tuwien/endpoint/ContainerEndpointUnitTest.java
@@ -2,12 +2,11 @@ package at.tuwien.endpoint;
 
 import at.tuwien.BaseUnitTest;
 import at.tuwien.api.container.*;
-import at.tuwien.auth.PermissionEvaluatorImpl;
 import at.tuwien.config.ReadyConfig;
 import at.tuwien.endpoints.ContainerEndpoint;
 import at.tuwien.exception.*;
-import at.tuwien.repository.jpa.ContainerRepository;
 import at.tuwien.repository.jpa.ImageRepository;
+import at.tuwien.repository.jpa.UserRepository;
 import at.tuwien.service.impl.ContainerServiceImpl;
 import org.apache.http.auth.BasicUserPrincipal;
 import org.junit.jupiter.api.Test;
@@ -15,19 +14,14 @@ import org.junit.jupiter.api.extension.ExtendWith;
 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.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
 import org.springframework.security.access.AccessDeniedException;
 import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
-import org.springframework.security.test.context.support.WithMockUser;
+import org.springframework.security.test.context.support.WithUserDetails;
 import org.springframework.test.context.junit.jupiter.SpringExtension;
 
 import java.security.Principal;
-import java.util.List;
-import java.util.Objects;
 import java.util.Optional;
 
-import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.mockito.Mockito.*;
 
@@ -42,10 +36,7 @@ public class ContainerEndpointUnitTest extends BaseUnitTest {
     private ImageRepository imageRepository;
 
     @MockBean
-    private ContainerRepository containerRepository;
-
-    @MockBean
-    private PermissionEvaluatorImpl permissionEvaluator;
+    private UserRepository userRepository;
 
     @Autowired
     private ContainerEndpoint containerEndpoint;
@@ -54,227 +45,130 @@ public class ContainerEndpointUnitTest extends BaseUnitTest {
     private ContainerServiceImpl containerService;
 
     @Test
-    public void listAllDatabases_succeeds() {
-        when(containerService.getAll())
-                .thenReturn(List.of(CONTAINER_1));
-
-        final ResponseEntity<List<ContainerBriefDto>> response = containerEndpoint.findAll(null);
-
-        /* test */
-        assertEquals(HttpStatus.OK, response.getStatusCode());
-        assertEquals(1, Objects.requireNonNull(response.getBody()).size());
-    }
-
-    @Test
-    @WithMockUser(roles = "RESEARCHER")
-    public void create_succeeds() throws ImageNotFoundException, DockerClientException, UserNotFoundException, ContainerAlreadyExistsException {
+    public void create_noAuth_fails() {
         final ContainerCreateRequestDto request = ContainerCreateRequestDto.builder()
                 .name(CONTAINER_1_NAME)
-                .repository(IMAGE_1.getRepository())
-                .tag(IMAGE_1.getTag())
+                .repository(IMAGE_1_REPOSITORY)
+                .tag(IMAGE_1_TAG)
                 .build();
-        final Principal principal = new BasicUserPrincipal(USER_1_USERNAME);
 
         /* mock */
-        when(containerService.create(request, principal))
-                .thenReturn(CONTAINER_1);
-
-        final ResponseEntity<ContainerBriefDto> response = containerEndpoint.create(request, principal);
+        when(imageRepository.findByRepositoryAndTag(IMAGE_1_REPOSITORY, IMAGE_1_TAG))
+                .thenReturn(Optional.of(IMAGE_1));
+        when(userRepository.findByUsername(USER_1_USERNAME))
+                .thenReturn(Optional.of(USER_1));
 
         /* test */
-        assertEquals(HttpStatus.CREATED, response.getStatusCode());
-        assertEquals(CONTAINER_1_NAME, Objects.requireNonNull(response.getBody()).getName());
+        assertThrows(AuthenticationCredentialsNotFoundException.class, () -> {
+            containerEndpoint.create(request, null);
+        });
     }
 
     @Test
-    @WithMockUser(roles = "RESEARCHER")
-    public void create_noImage_fails() {
+    @WithUserDetails(USER_4_USERNAME)
+    public void create_notRole_fails() {
         final ContainerCreateRequestDto request = ContainerCreateRequestDto.builder()
                 .name(CONTAINER_1_NAME)
                 .repository(IMAGE_1_REPOSITORY)
                 .tag(IMAGE_1_TAG)
                 .build();
-        final Principal principal = new BasicUserPrincipal(USER_1_USERNAME);
+        final Principal principal = new BasicUserPrincipal(USER_4_USERNAME);
 
         /* mock */
         when(imageRepository.findByRepositoryAndTag(IMAGE_1_REPOSITORY, IMAGE_1_TAG))
-                .thenReturn(Optional.empty());
+                .thenReturn(Optional.of(IMAGE_1));
+        when(userRepository.findByUsername(USER_1_USERNAME))
+                .thenReturn(Optional.of(USER_1));
 
-        assertThrows(ImageNotFoundException.class, () -> {
+        /* test */
+        assertThrows(AccessDeniedException.class, () -> {
             containerEndpoint.create(request, principal);
         });
     }
 
     @Test
-    public void create_noAuth_fails() {
+    @WithUserDetails(USER_2_USERNAME)
+    public void create_notResearcher_fails() {
         final ContainerCreateRequestDto request = ContainerCreateRequestDto.builder()
                 .name(CONTAINER_1_NAME)
                 .repository(IMAGE_1_REPOSITORY)
                 .tag(IMAGE_1_TAG)
                 .build();
-        final Principal principal = new BasicUserPrincipal(USER_1_USERNAME);
+        final Principal principal = new BasicUserPrincipal(USER_2_USERNAME);
 
-        assertThrows(AuthenticationCredentialsNotFoundException.class, () -> {
-            containerEndpoint.create(request, principal);
-        });
-    }
-
-    @Test
-    public void findById_succeeds() throws ContainerNotFoundException, DockerClientException, ContainerNotRunningException {
-        when(containerService.find(CONTAINER_1_ID))
-                .thenReturn(CONTAINER_1);
-
-        /* test */
-        final ResponseEntity<ContainerDto> response = containerEndpoint.findById(CONTAINER_1_ID);
-        assertEquals(HttpStatus.OK, response.getStatusCode());
-    }
-
-    @Test
-    public void findById_notFound_fails() throws ContainerNotFoundException, DockerClientException, ContainerNotRunningException {
-        doThrow(ContainerNotFoundException.class)
-                .when(containerService)
-                .inspect(CONTAINER_1_ID);
-
-        /* test */
-        assertThrows(ContainerNotFoundException.class, () -> {
-            containerEndpoint.findById(CONTAINER_1_ID);
-        });
-    }
-
-    @Test
-    public void findById_docker_fails() throws ContainerNotFoundException, DockerClientException, ContainerNotRunningException {
-        doThrow(DockerClientException.class)
-                .when(containerService)
-                .inspect(CONTAINER_1_ID);
-
-        /* test */
-        assertThrows(DockerClientException.class, () -> {
-            containerEndpoint.findById(CONTAINER_1_ID);
-        });
-    }
-
-    @Test
-    public void findById_notRunning_fails() throws ContainerNotFoundException, DockerClientException, ContainerNotRunningException {
-        doThrow(ContainerNotRunningException.class)
-                .when(containerService)
-                .inspect(CONTAINER_1_ID);
+        /* mock */
+        when(imageRepository.findByRepositoryAndTag(IMAGE_1_REPOSITORY, IMAGE_1_TAG))
+                .thenReturn(Optional.of(IMAGE_1));
+        when(userRepository.findByUsername(USER_1_USERNAME))
+                .thenReturn(Optional.of(USER_1));
 
         /* test */
-        assertThrows(ContainerNotRunningException.class, () -> {
-            containerEndpoint.findById(CONTAINER_1_ID);
+        assertThrows(AccessDeniedException.class, () -> {
+            containerEndpoint.create(request, principal);
         });
     }
 
     @Test
-    @WithMockUser(roles = "RESEARCHER")
-    public void modify_start_succeeds() throws DockerClientException, ContainerNotFoundException {
-        final ContainerChangeDto request = ContainerChangeDto.builder()
-                .action(ContainerActionTypeDto.START)
-                .build();
-        when(containerService.start(CONTAINER_1_ID))
-                .thenReturn(CONTAINER_1);
-
-        /* test */
-        final ResponseEntity<ContainerBriefDto> response = containerEndpoint.modify(CONTAINER_1_ID, request);
-        assertEquals(HttpStatus.ACCEPTED, response.getStatusCode());
-        assertEquals(CONTAINER_1_ID, Objects.requireNonNull(response.getBody()).getId());
-    }
-
-    @Test
-    @WithMockUser(roles = "RESEARCHER")
-    public void modify_stop_succeeds() throws DockerClientException, ContainerNotFoundException, ContainerStillRunningException {
-        final ContainerChangeDto request = ContainerChangeDto.builder()
-                .action(ContainerActionTypeDto.STOP)
+    @WithUserDetails(USER_3_USERNAME)
+    public void create_notResearcher2_fails() {
+        final ContainerCreateRequestDto request = ContainerCreateRequestDto.builder()
+                .name(CONTAINER_1_NAME)
+                .repository(IMAGE_1_REPOSITORY)
+                .tag(IMAGE_1_TAG)
                 .build();
-        when(containerService.stop(CONTAINER_1_ID))
-                .thenReturn(CONTAINER_1);
-
-        /* test */
-        final ResponseEntity<ContainerBriefDto> response = containerEndpoint.modify(CONTAINER_1_ID, request);
-        assertEquals(HttpStatus.ACCEPTED, response.getStatusCode());
-        assertEquals(CONTAINER_1_ID, Objects.requireNonNull(response.getBody()).getId());
-    }
+        final Principal principal = new BasicUserPrincipal(USER_3_USERNAME);
 
-    @Test
-    @WithMockUser(roles = "RESEARCHER")
-    public void modify_startDocker_fails() throws DockerClientException, ContainerNotFoundException {
-        final ContainerChangeDto request = ContainerChangeDto.builder()
-                .action(ContainerActionTypeDto.START)
-                .build();
-        when(containerService.start(CONTAINER_1_ID))
-                .thenThrow(DockerClientException.class);
+        /* mock */
+        when(imageRepository.findByRepositoryAndTag(IMAGE_1_REPOSITORY, IMAGE_1_TAG))
+                .thenReturn(Optional.of(IMAGE_1));
+        when(userRepository.findByUsername(USER_1_USERNAME))
+                .thenReturn(Optional.of(USER_1));
 
         /* test */
-        assertThrows(DockerClientException.class, () -> {
-            containerEndpoint.modify(CONTAINER_1_ID, request);
+        assertThrows(AccessDeniedException.class, () -> {
+            containerEndpoint.create(request, principal);
         });
     }
 
     @Test
-    @WithMockUser(roles = "RESEARCHER")
-    public void modify_stopDocker_fails() throws DockerClientException, ContainerNotFoundException {
-        final ContainerChangeDto request = ContainerChangeDto.builder()
-                .action(ContainerActionTypeDto.STOP)
+    @WithUserDetails(USER_1_USERNAME)
+    public void create_noImage_fails() {
+        final ContainerCreateRequestDto request = ContainerCreateRequestDto.builder()
+                .name(CONTAINER_1_NAME)
+                .repository(IMAGE_1_REPOSITORY)
+                .tag(IMAGE_1_TAG)
                 .build();
-        when(containerService.stop(CONTAINER_1_ID))
-                .thenThrow(DockerClientException.class);
-
-        /* test */
-        assertThrows(DockerClientException.class, () -> {
-            containerEndpoint.modify(CONTAINER_1_ID, request);
-        });
-    }
+        final Principal principal = new BasicUserPrincipal(USER_1_USERNAME);
 
-    @Test
-    @WithMockUser(roles = "RESEARCHER")
-    public void modify_stopNoContainer_fails() throws DockerClientException, ContainerNotFoundException {
-        final ContainerChangeDto request = ContainerChangeDto.builder()
-                .action(ContainerActionTypeDto.STOP)
-                .build();
-        when(containerService.stop(CONTAINER_1_ID))
-                .thenThrow(ContainerNotFoundException.class);
+        /* mock */
+        when(imageRepository.findByRepositoryAndTag(IMAGE_1_REPOSITORY, IMAGE_1_TAG))
+                .thenReturn(Optional.empty());
 
-        /* test */
-        assertThrows(ContainerNotFoundException.class, () -> {
-            containerEndpoint.modify(CONTAINER_1_ID, request);
+        assertThrows(ImageNotFoundException.class, () -> {
+            containerEndpoint.create(request, principal);
         });
     }
 
     @Test
-    @WithMockUser(roles = "DEVELOPER")
-    public void delete_noContainer_fails() {
-        doReturn(true)
-                .when(permissionEvaluator)
-                .hasPermission(any(), eq(CONTAINER_1_ID), eq("DELETE_CONTAINER"));
+    public void findAll_noAuth_fails() {
+        /* mock */
+        when(imageRepository.findByRepositoryAndTag(IMAGE_1_REPOSITORY, IMAGE_1_TAG))
+                .thenReturn(Optional.empty());
 
-        /* test */
-        assertThrows(ContainerNotFoundException.class, () -> {
-            containerEndpoint.delete(CONTAINER_1_ID);
-        });
+        containerEndpoint.findAll(null);
     }
 
     @Test
-    @WithMockUser(roles = "DEVELOPER")
-    public void delete_success() throws DockerClientException, ContainerStillRunningException, ContainerNotFoundException {
-        doReturn(true)
-                .when(permissionEvaluator)
-                .hasPermission(any(), eq(CONTAINER_1_ID), eq("DELETE_CONTAINER"));
-
-        /* mock */
-        when(containerRepository.findById(CONTAINER_1_ID))
-                .thenReturn(Optional.of(CONTAINER_1));
+    @WithUserDetails(USER_4_USERNAME)
+    public void findAll_noRole_succeeds() {
+        final Principal principal = new BasicUserPrincipal(USER_4_USERNAME);
 
-        /* test */
-        final ResponseEntity<?> response = containerEndpoint.delete(CONTAINER_1_ID);
-        assertEquals(HttpStatus.OK, response.getStatusCode());
+        containerEndpoint.findAll(principal);
     }
 
     @Test
-    @WithMockUser(roles = "RESEARCHER")
+    @WithUserDetails(USER_1_USERNAME)
     public void delete_notDeveloper_fails() {
-        doReturn(true)
-                .when(permissionEvaluator)
-                .hasPermission(any(), eq(CONTAINER_1_ID), eq("DELETE_CONTAINER"));
 
         /* test */
         assertThrows(AccessDeniedException.class, () -> {
@@ -283,27 +177,11 @@ public class ContainerEndpointUnitTest extends BaseUnitTest {
     }
 
     @Test
-    @WithMockUser(roles = "DEVELOPER")
-    public void delete_docker_fails() {
-        doReturn(true)
-                .when(permissionEvaluator)
-                .hasPermission(any(), eq(CONTAINER_1_ID), eq("DELETE_CONTAINER"));
+    @WithUserDetails(USER_1_USERNAME)
+    public void delete_noRoles_fails() {
 
         /* test */
-        assertThrows(DockerClientException.class, () -> {
-            containerEndpoint.delete(CONTAINER_1_ID);
-        });
-    }
-
-    @Test
-    @WithMockUser(roles = "DEVELOPER")
-    public void delete_dockerStillRunning_fails() {
-        doReturn(true)
-                .when(permissionEvaluator)
-                .hasPermission(any(), eq(CONTAINER_1_ID), eq("DELETE_CONTAINER"));
-
-        /* test */
-        assertThrows(ContainerStillRunningException.class, () -> {
+        assertThrows(AccessDeniedException.class, () -> {
             containerEndpoint.delete(CONTAINER_1_ID);
         });
     }
diff --git a/fda-container-service/rest-service/src/test/java/at/tuwien/service/ContainerServiceIntegrationTest.java b/fda-container-service/rest-service/src/test/java/at/tuwien/service/ContainerServiceIntegrationTest.java
index 353804e9f5..b270b5e403 100644
--- a/fda-container-service/rest-service/src/test/java/at/tuwien/service/ContainerServiceIntegrationTest.java
+++ b/fda-container-service/rest-service/src/test/java/at/tuwien/service/ContainerServiceIntegrationTest.java
@@ -65,7 +65,6 @@ public class ContainerServiceIntegrationTest extends BaseUnitTest {
     @Autowired
     private DockerUtil dockerUtil;
 
-    @Transactional
     @BeforeEach
     public void beforeEach() {
         afterEach();
@@ -106,7 +105,6 @@ public class ContainerServiceIntegrationTest extends BaseUnitTest {
         containerRepository.save(CONTAINER_2);
     }
 
-    @Transactional
     @AfterEach
     public void afterEach() {
         /* stop containers and remove them */
diff --git a/fda-container-service/rest-service/src/test/resources/docker/inspect_running.json b/fda-container-service/rest-service/src/test/resources/docker/inspect_running.json
new file mode 100644
index 0000000000..13b133312e
--- /dev/null
+++ b/fda-container-service/rest-service/src/test/resources/docker/inspect_running.json
@@ -0,0 +1,251 @@
+{
+  "Id": "37e0b9e40c004e8765fcfcd8830c8b29988fb5f3e847ad2e822b73759a938bdb",
+  "Created": "2022-11-16T16:55:46.906703156Z",
+  "Path": "docker-entrypoint.sh",
+  "Args": [
+    "mysqld"
+  ],
+  "State": {
+    "Status": "running",
+    "Running": true,
+    "Paused": false,
+    "Restarting": false,
+    "OOMKilled": false,
+    "Dead": false,
+    "Pid": 0,
+    "ExitCode": 0,
+    "Error": "",
+    "StartedAt": "0001-01-01T00:00:00Z",
+    "FinishedAt": "0001-01-01T00:00:00Z"
+  },
+  "Image": "sha256:61ff56a02874cff48f63dd41974a64ecb00305e98f56f011da318079ab3a2aca",
+  "ResolvConfPath": "",
+  "HostnamePath": "",
+  "HostsPath": "",
+  "LogPath": "",
+  "Name": "/dbrepo-userdb-fda-userdb-u01",
+  "RestartCount": 0,
+  "Driver": "overlay2",
+  "Platform": "linux",
+  "MountLabel": "",
+  "ProcessLabel": "",
+  "AppArmorProfile": "",
+  "ExecIDs": null,
+  "HostConfig": {
+    "Binds": [
+      "/tmp:/tmp:rw",
+      "dbrepo-userdb-fda-userdb-u01:/var/lib/mysql:rw"
+    ],
+    "ContainerIDFile": "",
+    "LogConfig": {
+      "Type": "json-file",
+      "Config": {}
+    },
+    "NetworkMode": "userdb",
+    "PortBindings": {
+      "5432/tcp": [
+        {
+          "HostIp": "",
+          "HostPort": "32125"
+        }
+      ]
+    },
+    "RestartPolicy": {
+      "Name": "always",
+      "MaximumRetryCount": 0
+    },
+    "AutoRemove": false,
+    "VolumeDriver": "",
+    "VolumesFrom": null,
+    "CapAdd": null,
+    "CapDrop": null,
+    "CgroupnsMode": "host",
+    "Dns": null,
+    "DnsOptions": null,
+    "DnsSearch": null,
+    "ExtraHosts": null,
+    "GroupAdd": null,
+    "IpcMode": "private",
+    "Cgroup": "",
+    "Links": null,
+    "OomScoreAdj": 0,
+    "PidMode": "",
+    "Privileged": false,
+    "PublishAllPorts": false,
+    "ReadonlyRootfs": false,
+    "SecurityOpt": null,
+    "UTSMode": "",
+    "UsernsMode": "",
+    "ShmSize": 67108864,
+    "Runtime": "runc",
+    "ConsoleSize": [
+      0,
+      0
+    ],
+    "Isolation": "",
+    "CpuShares": 0,
+    "Memory": 0,
+    "NanoCpus": 0,
+    "CgroupParent": "",
+    "BlkioWeight": 0,
+    "BlkioWeightDevice": null,
+    "BlkioDeviceReadBps": null,
+    "BlkioDeviceWriteBps": null,
+    "BlkioDeviceReadIOps": null,
+    "BlkioDeviceWriteIOps": null,
+    "CpuPeriod": 0,
+    "CpuQuota": 0,
+    "CpuRealtimePeriod": 0,
+    "CpuRealtimeRuntime": 0,
+    "CpusetCpus": "",
+    "CpusetMems": "",
+    "Devices": null,
+    "DeviceCgroupRules": null,
+    "DeviceRequests": null,
+    "KernelMemory": 0,
+    "KernelMemoryTCP": 0,
+    "MemoryReservation": 0,
+    "MemorySwap": 0,
+    "MemorySwappiness": null,
+    "OomKillDisable": false,
+    "PidsLimit": null,
+    "Ulimits": null,
+    "CpuCount": 0,
+    "CpuPercent": 0,
+    "IOMaximumIOps": 0,
+    "IOMaximumBandwidth": 0,
+    "MaskedPaths": [
+      "/proc/asound",
+      "/proc/acpi",
+      "/proc/kcore",
+      "/proc/keys",
+      "/proc/latency_stats",
+      "/proc/timer_list",
+      "/proc/timer_stats",
+      "/proc/sched_debug",
+      "/proc/scsi",
+      "/sys/firmware"
+    ],
+    "ReadonlyPaths": [
+      "/proc/bus",
+      "/proc/fs",
+      "/proc/irq",
+      "/proc/sys",
+      "/proc/sysrq-trigger"
+    ]
+  },
+  "GraphDriver": {
+    "Data": {
+      "LowerDir": "/var/lib/docker/overlay2/8a99e2be7f5bf6dec6f797f4d56f18ecd3da3c89618f5550a6ecafe9a4589ff2-init/diff:/var/lib/docker/overlay2/cb0b45ec25ff19bffbe3320ce72fbd9eb3a8c368277f5f059468043b2c329ed4/diff:/var/lib/docker/overlay2/919eb80e1f4e8923c5bd2386edcfd9a808971a11425d11101cf8ae7c800b08e7/diff:/var/lib/docker/overlay2/2fc5924ce3479c8d0e5786ee3a30d75a88683e8b6020b3350347de8217939305/diff:/var/lib/docker/overlay2/aeea12f97f79b33bc9d1533ebd69d474cb0e1251ba56690436bd12f56b3fdb74/diff:/var/lib/docker/overlay2/b0c45a33f5faf53ceb77f855b2edcbf005206af8fc3a6a80b1bb1215a1e8675e/diff:/var/lib/docker/overlay2/fb57deba6dcfda2684dbc39114e38eea34c27caca64960b7f16e1a6ffa7338ba/diff:/var/lib/docker/overlay2/bb27c7e4ba3673f3d06e2dbca624a55b93ae4996682fa572c3e8aa1ede6c341d/diff:/var/lib/docker/overlay2/f2b38526a2e3ba96ec37b2fd3348ae6b257a2c896e98b8bd02aaf460d8e8b168/diff",
+      "MergedDir": "/var/lib/docker/overlay2/8a99e2be7f5bf6dec6f797f4d56f18ecd3da3c89618f5550a6ecafe9a4589ff2/merged",
+      "UpperDir": "/var/lib/docker/overlay2/8a99e2be7f5bf6dec6f797f4d56f18ecd3da3c89618f5550a6ecafe9a4589ff2/diff",
+      "WorkDir": "/var/lib/docker/overlay2/8a99e2be7f5bf6dec6f797f4d56f18ecd3da3c89618f5550a6ecafe9a4589ff2/work"
+    },
+    "Name": "overlay2"
+  },
+  "Mounts": [
+    {
+      "Type": "bind",
+      "Source": "/tmp",
+      "Destination": "/tmp",
+      "Mode": "rw",
+      "RW": true,
+      "Propagation": "rprivate"
+    },
+    {
+      "Type": "volume",
+      "Name": "dbrepo-userdb-fda-userdb-u01",
+      "Source": "/var/lib/docker/volumes/dbrepo-userdb-fda-userdb-u01/_data",
+      "Destination": "/var/lib/mysql",
+      "Driver": "local",
+      "Mode": "rw",
+      "RW": true,
+      "Propagation": ""
+    }
+  ],
+  "Config": {
+    "Hostname": "dbrepo-userdb-fda-userdb-u01",
+    "Domainname": "",
+    "User": "",
+    "AttachStdin": false,
+    "AttachStdout": false,
+    "AttachStderr": false,
+    "ExposedPorts": {
+      "3306/tcp": {}
+    },
+    "Tty": false,
+    "OpenStdin": false,
+    "StdinOnce": false,
+    "Env": [
+      "MARIADB_USER=mariadb",
+      "MARIADB_PASSWORD=mariadb",
+      "MARIADB_ROOT_PASSWORD=mariadb",
+      "UZERNAME=root",
+      "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
+      "GOSU_VERSION=1.14",
+      "LANG=C.UTF-8",
+      "MARIADB_MAJOR=10.5",
+      "MARIADB_VERSION=1:10.5.18+maria~ubu2004"
+    ],
+    "Cmd": [
+      "mysqld"
+    ],
+    "Image": "mariadb:10.5",
+    "Volumes": {
+      "/var/lib/mysql": {}
+    },
+    "WorkingDir": "",
+    "Entrypoint": [
+      "docker-entrypoint.sh"
+    ],
+    "OnBuild": null,
+    "Labels": {
+      "org.opencontainers.image.authors": "MariaDB Community",
+      "org.opencontainers.image.base.name": "docker.io/library/ubuntu:focal",
+      "org.opencontainers.image.description": "MariaDB Database for relational SQL",
+      "org.opencontainers.image.documentation": "https://hub.docker.com/_/mariadb/",
+      "org.opencontainers.image.licenses": "GPL-2.0",
+      "org.opencontainers.image.source": "https://github.com/MariaDB/mariadb-docker",
+      "org.opencontainers.image.title": "MariaDB Database",
+      "org.opencontainers.image.url": "https://github.com/MariaDB/mariadb-docker",
+      "org.opencontainers.image.vendor": "MariaDB Community",
+      "org.opencontainers.image.version": "10.5.18"
+    }
+  },
+  "NetworkSettings": {
+    "Bridge": "",
+    "SandboxID": "",
+    "HairpinMode": false,
+    "LinkLocalIPv6Address": "",
+    "LinkLocalIPv6PrefixLen": 0,
+    "Ports": {},
+    "SandboxKey": "",
+    "SecondaryIPAddresses": null,
+    "SecondaryIPv6Addresses": null,
+    "EndpointID": "",
+    "Gateway": "",
+    "GlobalIPv6Address": "",
+    "GlobalIPv6PrefixLen": 0,
+    "IPAddress": "",
+    "IPPrefixLen": 0,
+    "IPv6Gateway": "",
+    "MacAddress": "",
+    "Networks": {
+      "userdb": {
+        "IPAMConfig": null,
+        "Links": null,
+        "Aliases": null,
+        "NetworkID": "",
+        "EndpointID": "",
+        "Gateway": "",
+        "IPAddress": "",
+        "IPPrefixLen": 0,
+        "IPv6Gateway": "",
+        "GlobalIPv6Address": "",
+        "GlobalIPv6PrefixLen": 0,
+        "MacAddress": "",
+        "DriverOpts": null
+      }
+    }
+  }
+}
\ No newline at end of file
-- 
GitLab