Add model-loader integration tests

- add integration tests that assert the external communication towards other services using Wiremock
- remove tests that are asserting getters and setters of objects

Issue-ID: AAI-3826
Change-Id: I1f627801869f40cb0eaa61b10148b41bd3b1bdb8
Signed-off-by: Fiete Ostkamp <Fiete.Ostkamp@telekom.de>
diff --git a/pom.xml b/pom.xml
index 644e408..1bf31f4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -384,6 +384,17 @@
 			<groupId>org.springframework.boot</groupId>
 			<artifactId>spring-boot-starter-test</artifactId>
 			<scope>test</scope>
+			<exclusions>
+				<exclusion>
+					<groupId>com.vaadin.external.google</groupId>
+					<artifactId>android-json</artifactId>
+				</exclusion>
+			</exclusions>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.cloud</groupId>
+			<artifactId>spring-cloud-contract-wiremock</artifactId>
+			<scope>test</scope>
 		</dependency>
 	</dependencies>
 
diff --git a/src/main/java/org/onap/aai/modelloader/config/BeanConfig.java b/src/main/java/org/onap/aai/modelloader/config/BeanConfig.java
index 8f7b2bb..63956e2 100644
--- a/src/main/java/org/onap/aai/modelloader/config/BeanConfig.java
+++ b/src/main/java/org/onap/aai/modelloader/config/BeanConfig.java
@@ -30,9 +30,11 @@
 import org.onap.aai.modelloader.service.ModelLoaderMsgs;
 import org.onap.sdc.api.IDistributionClient;
 import org.onap.sdc.impl.DistributionClientFactory;
+import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.web.client.RestTemplate;
 
 @Configuration
 public class BeanConfig {
@@ -44,13 +46,18 @@
     private String configDir;
 
     @Bean
-    public ModelLoaderConfig modelLoaderConfig() throws IOException {
+    public Properties configProperties() throws IOException {
         // Load model loader system configuration
         logger.info(ModelLoaderMsgs.LOADING_CONFIGURATION);
-        ModelLoaderConfig.setConfigHome(configDir);
-        Properties configProperties = new Properties();
         InputStream configInputStream = Files.newInputStream(Paths.get(configDir, "model-loader.properties"));
+        Properties configProperties = new Properties();
         configProperties.load(configInputStream);
+        return configProperties;
+    }
+
+    @Bean
+    public ModelLoaderConfig modelLoaderConfig(Properties configProperties) {
+        ModelLoaderConfig.setConfigHome(configDir);
         return new ModelLoaderConfig(configProperties);
     }
     
@@ -58,4 +65,9 @@
     public IDistributionClient iDistributionClient() {
         return DistributionClientFactory.createDistributionClient();
     }
+
+    @Bean
+    public RestTemplate restTemplate() {
+        return new RestTemplate();
+    }
 }
diff --git a/src/main/java/org/onap/aai/modelloader/config/DistributionClientStartupConfig.java b/src/main/java/org/onap/aai/modelloader/config/DistributionClientStartupConfig.java
index 84c79f2..cd9d919 100644
--- a/src/main/java/org/onap/aai/modelloader/config/DistributionClientStartupConfig.java
+++ b/src/main/java/org/onap/aai/modelloader/config/DistributionClientStartupConfig.java
@@ -33,10 +33,10 @@
 import org.onap.sdc.utils.DistributionActionResultEnum;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.boot.context.event.ApplicationReadyEvent;
+import org.springframework.context.annotation.Configuration;
 import org.springframework.context.event.EventListener;
-import org.springframework.stereotype.Component;
 
-@Component
+@Configuration
 @ConditionalOnProperty(value = "ml.distribution.connection.enabled", havingValue = "true", matchIfMissing = true)
 public class DistributionClientStartupConfig {
 
@@ -57,7 +57,8 @@
     protected void initSdcClient() {
         // Initialize distribution client
         logger.debug(ModelLoaderMsgs.INITIALIZING, "Initializing distribution client...");
-        IDistributionClientResult initResult = client.init(config, eventCallback);
+        IDistributionClientResult initResult = null;
+        initResult = client.init(config, eventCallback);
 
         if (initResult.getDistributionActionResult() == DistributionActionResultEnum.SUCCESS) {
             // Start distribution client
diff --git a/src/main/java/org/onap/aai/modelloader/config/ModelLoaderConfig.java b/src/main/java/org/onap/aai/modelloader/config/ModelLoaderConfig.java
index 7da90d9..6723e75 100644
--- a/src/main/java/org/onap/aai/modelloader/config/ModelLoaderConfig.java
+++ b/src/main/java/org/onap/aai/modelloader/config/ModelLoaderConfig.java
@@ -77,6 +77,9 @@
     protected static final String PROP_ML_DISTRIBUTION_HTTP_PROXY_PORT = PREFIX_DISTRIBUTION_CLIENT + "HTTP_PROXY_PORT";
     protected static final String PROP_ML_DISTRIBUTION_HTTPS_PROXY_HOST = PREFIX_DISTRIBUTION_CLIENT + "HTTPS_PROXY_HOST";
     protected static final String PROP_ML_DISTRIBUTION_HTTPS_PROXY_PORT = PREFIX_DISTRIBUTION_CLIENT + "HTTPS_PROXY_PORT";
+    protected static final String PROP_ML_DISTRIBUTION_SASL_JAAS_CONFIG = PREFIX_DISTRIBUTION_CLIENT + "SASL_JAAS_CONFIG";
+    protected static final String PROP_ML_DISTRIBUTION_SASL_MECHANISM = PREFIX_DISTRIBUTION_CLIENT + "SASL_MECHANISM";
+    protected static final String PROP_ML_DISTRIBUTION_SECURITY_PROTOCOL = PREFIX_DISTRIBUTION_CLIENT + "SECURITY_PROTOCOL";
     protected static final String PROP_AAI_BASE_URL = PREFIX_AAI + "BASE_URL";
     protected static final String PROP_AAI_KEYSTORE_FILE = PREFIX_AAI + SUFFIX_KEYSTORE_FILE;
     protected static final String PROP_AAI_KEYSTORE_PASSWORD = PREFIX_AAI + SUFFIX_KEYSTORE_PASS;
@@ -413,4 +416,35 @@
         return Integer.parseInt(connectTimeout);
     }
 
+    @Override
+    public String getKafkaSaslJaasConfig() {
+        String saslJaasConfFromEnv = System.getenv("SASL_JAAS_CONFIG");
+        if(saslJaasConfFromEnv != null) {
+            return saslJaasConfFromEnv;
+        }
+        if(get(PROP_ML_DISTRIBUTION_SASL_JAAS_CONFIG) != null) {
+            return get(PROP_ML_DISTRIBUTION_SASL_JAAS_CONFIG);
+        }
+        return null;
+    }
+
+    @Override
+    public String getKafkaSaslMechanism() {
+        if(get(PROP_ML_DISTRIBUTION_SASL_MECHANISM) != null) {
+            return get(PROP_ML_DISTRIBUTION_SASL_MECHANISM);
+        }
+        return System.getenv().getOrDefault("SASL_MECHANISM", "SCRAM-SHA-512");
+    }
+
+    /**
+     * One of PLAINTEXT, SSL, SASL_PLAINTEXT, SASL_SSL
+     */
+    @Override
+    public String getKafkaSecurityProtocolConfig() {
+        if(get(PROP_ML_DISTRIBUTION_SECURITY_PROTOCOL) != null) {
+            return get(PROP_ML_DISTRIBUTION_SECURITY_PROTOCOL);
+        }
+        return System.getenv().getOrDefault("SECURITY_PROTOCOL", "SASL_PLAINTEXT");
+    }
+
 }
diff --git a/src/main/java/org/onap/aai/modelloader/notification/NotificationDataImpl.java b/src/main/java/org/onap/aai/modelloader/notification/NotificationDataImpl.java
index 566415e..3eb07f3 100644
--- a/src/main/java/org/onap/aai/modelloader/notification/NotificationDataImpl.java
+++ b/src/main/java/org/onap/aai/modelloader/notification/NotificationDataImpl.java
@@ -20,98 +20,28 @@
  */
 package org.onap.aai.modelloader.notification;
 
-import java.util.Collections;
 import java.util.List;
 import org.onap.sdc.api.notification.IArtifactInfo;
 import org.onap.sdc.api.notification.INotificationData;
 import org.onap.sdc.api.notification.IResourceInstance;
 
+import lombok.Data;
+
+@Data
 public class NotificationDataImpl implements INotificationData {
 
     private String distributionID;
+    private String serviceName;
+    private String serviceVersion;
+    private String serviceUUID;
+    private String serviceDescription;
+    private List<IResourceInstance> resources;
+    private List<IArtifactInfo> serviceArtifacts;
+    private String serviceInvariantUUID;
+    private String workloadContext;
 
     @Override
-    public IArtifactInfo getArtifactMetadataByUUID(String arg0) {
+    public IArtifactInfo getArtifactMetadataByUUID(String uuid) {
         return null;
     }
-
-    @Override
-    public String getDistributionID() {
-        return distributionID;
-    }
-
-    public void setDistributionID(String distributionID) {
-        this.distributionID = distributionID;
-    }
-
-    @Override
-    public List<IResourceInstance> getResources() {
-        return Collections.emptyList();
-    }
-
-    @Override
-    public List<IArtifactInfo> getServiceArtifacts() {
-        return Collections.emptyList();
-    }
-
-    @Override
-    public String getServiceDescription() {
-        return null;
-    }
-
-    @Override
-    public String getServiceInvariantUUID() {
-        return null;
-    }
-
-    @Override
-    public String getServiceName() {
-        return null;
-    }
-
-    @Override
-    public String getServiceUUID() {
-        return null;
-    }
-
-    @Override
-    public String getServiceVersion() {
-        return null;
-    }
-
-    @Override
-    public String getWorkloadContext() {
-        return null;
-    }
-
-    @Override
-    public void setWorkloadContext(String arg0) {
-        // Unsupported method - not expected to be called
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((distributionID == null) ? 0 : distributionID.hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj)
-            return true;
-        if (obj == null)
-            return false;
-        if (getClass() != obj.getClass())
-            return false;
-        NotificationDataImpl other = (NotificationDataImpl) obj;
-        if (distributionID == null) {
-            if (other.distributionID != null)
-                return false;
-        } else if (!distributionID.equals(other.distributionID))
-            return false;
-        return true;
-    }
-
 }
diff --git a/src/main/java/org/onap/aai/modelloader/restclient/AaiRestClient.java b/src/main/java/org/onap/aai/modelloader/restclient/AaiRestClient.java
index 40aeacc..45f84d6 100644
--- a/src/main/java/org/onap/aai/modelloader/restclient/AaiRestClient.java
+++ b/src/main/java/org/onap/aai/modelloader/restclient/AaiRestClient.java
@@ -42,6 +42,7 @@
 import org.onap.aai.restclient.client.OperationResult;
 import org.onap.aai.restclient.client.RestClient;
 import org.onap.aai.restclient.enums.RestAuthenticationMode;
+import org.springframework.stereotype.Component;
 import org.w3c.dom.Document;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
@@ -52,6 +53,7 @@
  * Wrapper around the standard A&AI Rest Client interface. This currently uses Jersey client 1.x
  *
  */
+@Component
 public class AaiRestClient {
 
     public static final String HEADER_TRANS_ID = "X-TransactionId";
diff --git a/src/main/java/org/onap/aai/modelloader/restclient/HttpsBabelServiceClient.java b/src/main/java/org/onap/aai/modelloader/restclient/HttpsBabelServiceClient.java
index c76996f..0789996 100644
--- a/src/main/java/org/onap/aai/modelloader/restclient/HttpsBabelServiceClient.java
+++ b/src/main/java/org/onap/aai/modelloader/restclient/HttpsBabelServiceClient.java
@@ -229,8 +229,8 @@
         String resourceUrl = config.getBabelBaseUrl() + config.getBabelGenerateArtifactsUrl();
         WebResource webResource = client.resource(resourceUrl);
         ClientResponse response = webResource.type("application/json")
-                .header(AaiRestClient.HEADER_TRANS_ID, Collections.singletonList(transactionId))
-                .header(AaiRestClient.HEADER_FROM_APP_ID, Collections.singletonList(AaiRestClient.ML_APP_NAME))
+                .header(AaiRestClient.HEADER_TRANS_ID, transactionId)
+                .header(AaiRestClient.HEADER_FROM_APP_ID, AaiRestClient.ML_APP_NAME)
                 .post(ClientResponse.class, obj.toString());
         String sanitizedJson = JsonSanitizer.sanitize(response.getEntity(String.class));
 
diff --git a/src/main/java/org/onap/aai/modelloader/service/ArtifactInfoImpl.java b/src/main/java/org/onap/aai/modelloader/service/ArtifactInfoImpl.java
index 9af92be..f83e44d 100644
--- a/src/main/java/org/onap/aai/modelloader/service/ArtifactInfoImpl.java
+++ b/src/main/java/org/onap/aai/modelloader/service/ArtifactInfoImpl.java
@@ -20,116 +20,25 @@
  */
 package org.onap.aai.modelloader.service;
 
-import java.util.Collections;
 import java.util.List;
 import org.onap.sdc.api.notification.IArtifactInfo;
 
+import lombok.Data;
+
 /**
  * This class is an implementation of IArtifactInfo for test purposes.
  */
+@Data
 public class ArtifactInfoImpl implements IArtifactInfo {
 
     private String artifactName;
     private String artifactType;
     private String artifactDescription;
     private String artifactVersion;
-
-    @Override
-    public String getArtifactName() {
-        return artifactName;
-    }
-
-    public void setArtifactName(String artifactName) {
-        this.artifactName = artifactName;
-    }
-
-    @Override
-    public String getArtifactType() {
-        return artifactType;
-    }
-
-    public void setArtifactType(String artifactType) {
-        this.artifactType = artifactType;
-    }
-
-    @Override
-    public String getArtifactURL() {
-        return null;
-    }
-
-    @Override
-    public String getArtifactChecksum() {
-        return null;
-    }
-
-    @Override
-    public String getArtifactDescription() {
-        return artifactDescription;
-    }
-
-    public void setArtifactDescription(String artifactDescription) {
-        this.artifactDescription = artifactDescription;
-    }
-
-    @Override
-    public Integer getArtifactTimeout() {
-        return null;
-    }
-
-    @Override
-    public String getArtifactVersion() {
-        return artifactVersion;
-    }
-
-    public void setArtifactVersion(String artifactVersion) {
-        this.artifactVersion = artifactVersion;
-    }
-
-    @Override
-    public String getArtifactUUID() {
-        return null;
-    }
-
-    @Override
-    public IArtifactInfo getGeneratedArtifact() {
-        return null;
-    }
-
-    @Override
-    public List<IArtifactInfo> getRelatedArtifacts() {
-        return Collections.emptyList();
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (o == null || getClass() != o.getClass()) {
-            return false;
-        }
-
-        ArtifactInfoImpl that = (ArtifactInfoImpl) o;
-
-        if (artifactName != null ? !artifactName.equals(that.artifactName) : that.artifactName != null) {
-            return false;
-        }
-        if (artifactType != null ? !artifactType.equals(that.artifactType) : that.artifactType != null) {
-            return false;
-        }
-        if (artifactDescription != null ? !artifactDescription.equals(that.artifactDescription)
-                : that.artifactDescription != null) {
-            return false;
-        }
-        return artifactVersion != null ? artifactVersion.equals(that.artifactVersion) : that.artifactVersion == null;
-    }
-
-    @Override
-    public int hashCode() {
-        int result = artifactName != null ? artifactName.hashCode() : 0;
-        result = 31 * result + (artifactType != null ? artifactType.hashCode() : 0);
-        result = 31 * result + (artifactDescription != null ? artifactDescription.hashCode() : 0);
-        result = 31 * result + (artifactVersion != null ? artifactVersion.hashCode() : 0);
-        return result;
-    }
+    private String artifactURL;
+    private String artifactChecksum;
+    private Integer artifactTimeout;
+    private String artifactUUID;
+    private IArtifactInfo generatedArtifact;
+    private List<IArtifactInfo> relatedArtifacts;
 }
diff --git a/src/test/java/org/onap/aai/modelloader/DistributionClientTestConfiguration.java b/src/test/java/org/onap/aai/modelloader/DistributionClientTestConfiguration.java
new file mode 100644
index 0000000..1eed62f
--- /dev/null
+++ b/src/test/java/org/onap/aai/modelloader/DistributionClientTestConfiguration.java
@@ -0,0 +1,81 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2024 Deutsche Telekom AG Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.modelloader;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
+import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
+import static com.github.tomakehurst.wiremock.client.WireMock.get;
+import static com.github.tomakehurst.wiremock.client.WireMock.matching;
+import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Properties;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.context.event.ApplicationStartedEvent;
+import org.springframework.boot.test.context.TestConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Primary;
+import org.springframework.context.event.EventListener;
+
+@TestConfiguration
+public class DistributionClientTestConfiguration {
+
+  @Value("${CONFIG_HOME}")
+  private String configDir;
+
+  @Value("${wiremock.server.port}")
+  private int wiremockPort;
+
+  @Primary
+  @Bean(name = "testProperties")
+  public Properties configProperties() throws IOException {
+    // Load model loader system configuration
+    InputStream configInputStream = Files.newInputStream(Paths.get(configDir, "model-loader.properties"));
+    Properties configProperties = new Properties();
+    configProperties.load(configInputStream);
+
+    setOverrides(configProperties);
+
+    return configProperties;
+  }
+
+  private void setOverrides(Properties configProperties) {
+    configProperties.setProperty("ml.distribution.ASDC_ADDRESS", "localhost:" + wiremockPort);
+    configProperties.setProperty("ml.babel.BASE_URL", "http://localhost:" + wiremockPort);
+  }
+
+  @EventListener(ApplicationStartedEvent.class)
+  public void mockSdcInit() {
+    stubFor(get(urlEqualTo("/sdc/v1/artifactTypes"))
+        .withHeader("X-ECOMP-RequestID", matching(".+"))
+        .withHeader("X-ECOMP-InstanceID", equalTo("aai-ml-id-test"))
+        .willReturn(aResponse().withHeader("Content-Type", "application/json").withBodyFile("artifactTypes.json")));
+
+    stubFor(get(urlEqualTo("/sdc/v1/distributionKafkaData"))
+        .withHeader("X-ECOMP-RequestID", matching(".+"))
+        .withHeader("X-ECOMP-InstanceID", equalTo("aai-ml-id-test"))
+        .willReturn(aResponse().withHeader("Content-Type", "application/json").withBodyFile("kafkaBootstrap.json")));
+  }
+}
\ No newline at end of file
diff --git a/src/test/java/org/onap/aai/modelloader/TestModelLoaderApplication.java b/src/test/java/org/onap/aai/modelloader/TestModelLoaderApplication.java
deleted file mode 100644
index cd39066..0000000
--- a/src/test/java/org/onap/aai/modelloader/TestModelLoaderApplication.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * ============LICENSE_START=======================================================
- * org.onap.aai
- * ================================================================================
- * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
- * Copyright © 2017-2018 European Software Marketing Ltd.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *       http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-package org.onap.aai.modelloader;
-
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-import org.junit.jupiter.api.Test;
-
-/**
- * Tests for ModelLoaderApplication class.
- *
- */
-public class TestModelLoaderApplication {
-
-    static {
-        System.setProperty("CONFIG_HOME", "src/test/resources");
-    }
-
-    @Test
-    public void testServiceStarts() {
-        // The SDC Distribution Client is disabled.
-        ModelLoaderApplication.main(new String[0]);
-        assertTrue(true);
-    }
-
-}
diff --git a/src/test/java/org/onap/aai/modelloader/distribution/NotificationIntegrationTest.java b/src/test/java/org/onap/aai/modelloader/distribution/NotificationIntegrationTest.java
index 2645871..abdefd4 100644
--- a/src/test/java/org/onap/aai/modelloader/distribution/NotificationIntegrationTest.java
+++ b/src/test/java/org/onap/aai/modelloader/distribution/NotificationIntegrationTest.java
@@ -26,6 +26,7 @@
 
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
+import org.onap.aai.modelloader.notification.NotificationDataImpl;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.boot.test.context.SpringBootTest;
@@ -35,25 +36,26 @@
 
 @DirtiesContext
 @SpringBootTest(properties = { "model-loader.sdc.connection.enabled=true"})
-@EmbeddedKafka(partitions = 1, brokerProperties = { "listeners=PLAINTEXT://localhost:9092", "port=9092" })
+@EmbeddedKafka(partitions = 1, ports = 9092, topics = {"${topics.distribution.notification}"})
 public class NotificationIntegrationTest {
 
     @Autowired EventCallbackAspect eventCallbackAspect;
 
     @Autowired
-    private KafkaTemplate<String, String> kafkaTemplate;
+    private KafkaTemplate<String, NotificationDataImpl> kafkaTemplate;
 
-    @Value("${test.topic}")
+    @Value("${topics.distribution.notification}")
     private String topic;
 
     @Test
     @Disabled("This test is not yet implemented")
     public void thatActivateCallbackIsCalled()
       throws Exception {
-        String data = "Smth";
-
+        NotificationDataImpl notificationData = new NotificationDataImpl();
+        notificationData.setDistributionID("distributionID");
+    
         // TODO: send distribution event here
-        kafkaTemplate.send(topic, data);
+        kafkaTemplate.send(topic, notificationData);
 
         // TODO: mock distribution client requests to /sdc/v1/artifactTypes
         // TODO: mock distribution client requests to /sdc/v1/distributionKafkaData
diff --git a/src/test/java/org/onap/aai/modelloader/notification/ArtifactDownloadManagerTest.java b/src/test/java/org/onap/aai/modelloader/notification/ArtifactDownloadManagerTest.java
new file mode 100644
index 0000000..0985790
--- /dev/null
+++ b/src/test/java/org/onap/aai/modelloader/notification/ArtifactDownloadManagerTest.java
@@ -0,0 +1,107 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2024 Deutsche Telekom AG Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.modelloader.notification;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
+import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
+import static com.github.tomakehurst.wiremock.client.WireMock.get;
+import static com.github.tomakehurst.wiremock.client.WireMock.matching;
+import static com.github.tomakehurst.wiremock.client.WireMock.matchingJsonPath;
+import static com.github.tomakehurst.wiremock.client.WireMock.post;
+import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.http.entity.ContentType;
+import org.junit.jupiter.api.Test;
+import org.onap.aai.modelloader.DistributionClientTestConfiguration;
+import org.onap.aai.modelloader.entity.Artifact;
+import org.onap.aai.modelloader.entity.ArtifactType;
+import org.onap.aai.modelloader.service.ArtifactInfoImpl;
+import org.onap.sdc.api.notification.IArtifactInfo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock;
+import org.springframework.context.annotation.Import;
+import org.springframework.http.MediaType;
+import org.springframework.kafka.test.context.EmbeddedKafka;
+import org.springframework.test.annotation.DirtiesContext;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+
+@DirtiesContext
+@AutoConfigureWireMock(port = 0)
+@EmbeddedKafka(partitions = 1, ports = 9092, topics = {"${topics.distribution.notification}"})
+@SpringBootTest(properties = { "ml.distribution.connection.enabled=true" })
+@Import(DistributionClientTestConfiguration.class)
+public class ArtifactDownloadManagerTest {
+
+  @Autowired ArtifactDownloadManager artifactDownloadManager;
+
+  @Test
+  public void downloadArtifacts() throws JsonProcessingException {
+    NotificationDataImpl notificationData = new NotificationDataImpl();
+    notificationData.setDistributionID("distributionID");
+    notificationData.setServiceVersion("2.0");
+
+    stubFor(get(urlEqualTo("/sdc/v1/catalog/services/DemovlbCds/1.0/artifacts/service-TestSvc-csar.csar"))
+        .withHeader("Accept", equalTo(ContentType.APPLICATION_OCTET_STREAM.toString()))
+        .withHeader("X-ECOMP-RequestID", matching(".+"))
+        .withHeader("X-ECOMP-InstanceID", equalTo("aai-ml-id-test"))
+        .willReturn(aResponse()
+          .withHeader("Content-Type", MediaType.APPLICATION_OCTET_STREAM.toString())
+          .withBodyFile("service-TestSvc-csar.csar")));
+    
+    stubFor(
+        post(urlEqualTo("/services/babel-service/v1/app/generateArtifacts"))
+            .withHeader("X-TransactionId", equalTo("distributionID"))
+            .withHeader("X-FromAppId", equalTo("ModelLoader"))
+            .withHeader("Content-Type", equalTo(MediaType.APPLICATION_JSON_VALUE))
+            .withRequestBody(matchingJsonPath("$.artifactName", equalTo("service-TestSvc-csar.csar")))
+            .withRequestBody(matchingJsonPath("$.artifactVersion", equalTo("2.0")))
+            .withRequestBody(matchingJsonPath("$.csar", matching(".*")))
+            .willReturn(
+                aResponse()
+                    .withHeader("Content-Type", "application/json")
+                    .withBodyFile("service-TestSvc-csar-babel-response.json")));
+
+    ArtifactInfoImpl artifactInfo = new ArtifactInfoImpl();
+    artifactInfo.setArtifactName("service-TestSvc-csar.csar");
+    artifactInfo.setArtifactVersion("1.0");
+    artifactInfo.setArtifactURL("/sdc/v1/catalog/services/DemovlbCds/1.0/artifacts/service-TestSvc-csar.csar");
+    artifactInfo.setArtifactType("TOSCA_CSAR");
+    artifactInfo.setArtifactChecksum("ZmI5NzQ1MWViZGFkMjRjZWEwNTQzY2U0OWQwYjlmYjQ=");
+    artifactInfo.setArtifactUUID("f6f907f1-3f45-4fb4-8cbe-15a4c6ee16db");
+    List<IArtifactInfo> artifacts = new ArrayList<>();
+    artifacts.add(artifactInfo);
+    List<Artifact> modelArtifacts = new ArrayList<>(); // processed artifacts will be written to this list
+    List<Artifact> catalogArtifacts = new ArrayList<>(); // processed artifacts will be written to this list
+    boolean result = artifactDownloadManager.downloadArtifacts(notificationData, artifacts, modelArtifacts, catalogArtifacts);
+    
+    assertEquals(1, modelArtifacts.size());
+    assertEquals(ArtifactType.MODEL, modelArtifacts.get(0).getType());
+    assertTrue(result);
+  }
+
+}
diff --git a/src/test/java/org/onap/aai/modelloader/notification/ModelArtifactHandlerTest.java b/src/test/java/org/onap/aai/modelloader/notification/ModelArtifactHandlerTest.java
new file mode 100644
index 0000000..b1269ee
--- /dev/null
+++ b/src/test/java/org/onap/aai/modelloader/notification/ModelArtifactHandlerTest.java
@@ -0,0 +1,226 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2024 Deutsche Telekom AG Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.modelloader.notification;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.verify;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
+import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
+import static com.github.tomakehurst.wiremock.client.WireMock.deleteRequestedFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
+import static com.github.tomakehurst.wiremock.client.WireMock.ok;
+
+import java.util.List;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.onap.aai.modelloader.config.ModelLoaderConfig;
+import org.onap.aai.modelloader.entity.Artifact;
+import org.onap.aai.modelloader.entity.model.ModelArtifact;
+import org.onap.aai.modelloader.entity.model.ModelArtifactHandler;
+import org.onap.aai.modelloader.restclient.AaiRestClient;
+import org.onap.aai.restclient.client.OperationResult;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.client.RestTemplate;
+import org.w3c.dom.Node;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.github.tomakehurst.wiremock.client.WireMock;
+
+import java.util.ArrayList;
+
+@SpringBootTest
+@AutoConfigureWireMock(port = 0)
+public class ModelArtifactHandlerTest {
+
+  @Value("${wiremock.server.port}")
+  private int wiremockPort;
+
+  final ObjectMapper objectMapper = new ObjectMapper();
+  @Mock
+  ModelLoaderConfig config;
+  @InjectMocks
+  ModelArtifactHandler modelArtifactHandler;
+
+  @Autowired
+  AaiRestClient restClient;
+
+  @BeforeEach
+  public void setUp() {
+    when(config.getAaiBaseUrl()).thenReturn("http://localhost:" + wiremockPort);
+    when(config.getAaiModelUrl(any())).thenReturn("/aai/v28/service-design-and-creation/models/model/");
+  }
+
+  @Test
+  public void thatArtifactsCanBeCreated() {
+    WireMock.stubFor(
+        WireMock.get(urlEqualTo("/aai/v28/service-design-and-creation/models/model/modelInvariantId"))
+            .withHeader("Accept", equalTo("application/xml"))
+            .withHeader("X-TransactionId", equalTo("someId"))
+            .withHeader("X-FromAppId", equalTo("ModelLoader"))
+            .willReturn(
+                WireMock.aResponse()
+                    .withStatus(HttpStatus.NOT_FOUND.value())));
+
+    WireMock.stubFor(
+        WireMock.put(urlEqualTo("/aai/v28/service-design-and-creation/models/model/modelInvariantId"))
+            .withHeader("Content-Type", equalTo("application/xml"))
+            .withHeader("X-TransactionId", equalTo("someId"))
+            .withHeader("X-FromAppId", equalTo("ModelLoader"))
+            .willReturn(
+                WireMock.aResponse()
+                    .withStatus(HttpStatus.CREATED.value())));
+
+    ModelArtifact modelArtifact = new ModelArtifact();
+    modelArtifact.setModelInvariantId("modelInvariantId");
+    List<Artifact> artifacts = List.of(modelArtifact);
+    List<Artifact> completedArtifacts = new ArrayList<>();
+
+    boolean result = modelArtifactHandler.pushArtifacts(artifacts,
+        "someId", completedArtifacts, restClient);
+    assertTrue(result);
+    WireMock.verify(
+        WireMock.putRequestedFor(urlEqualTo("/aai/v28/service-design-and-creation/models/model/modelInvariantId")));
+  }
+
+  @Test
+  public void thatArtifactsCanBeUpdated() {
+    // Checks if model exists in resources service
+    WireMock.stubFor(
+        WireMock.get(urlEqualTo("/aai/v28/service-design-and-creation/models/model/modelInvariantId"))
+            .withHeader("Accept", equalTo("application/xml"))
+            .withHeader("X-TransactionId", equalTo("distributionId"))
+            .withHeader("X-FromAppId", equalTo("ModelLoader"))
+            .willReturn(
+                WireMock.aResponse()
+                    .withStatus(HttpStatus.OK.value())));
+
+    // Checks if specific version of model exists in aai-resources
+    WireMock.stubFor(
+        WireMock.get(urlEqualTo(
+            "/aai/v28/service-design-and-creation/models/model/modelInvariantId/model-vers/model-ver/modelVersionId"))
+            .withHeader("Accept", equalTo("application/xml"))
+            .withHeader("X-TransactionId", equalTo("distributionId"))
+            .withHeader("X-FromAppId", equalTo("ModelLoader"))
+            .willReturn(
+                WireMock.aResponse()
+                    .withStatus(HttpStatus.NOT_FOUND.value())));
+
+    WireMock.stubFor(
+        WireMock.put(urlEqualTo(
+            "/aai/v28/service-design-and-creation/models/model/modelInvariantId/model-vers/model-ver/modelVersionId"))
+            .withHeader("Content-Type", equalTo("application/xml"))
+            .withHeader("X-TransactionId", equalTo("distributionId"))
+            .withHeader("X-FromAppId", equalTo("ModelLoader"))
+            .willReturn(
+                WireMock.aResponse()
+                    .withStatus(HttpStatus.CREATED.value())));
+
+    ModelArtifact modelArtifact = new ModelArtifact();
+    modelArtifact.setModelInvariantId("modelInvariantId");
+    modelArtifact.setModelVerId("modelVersionId");
+    Node node = Mockito.mock(Node.class);
+    modelArtifact.setModelVer(node);
+    List<Artifact> artifacts = List.of(modelArtifact);
+    List<Artifact> completedArtifacts = new ArrayList<>();
+
+    boolean result = modelArtifactHandler.pushArtifacts(artifacts,
+        "distributionId", completedArtifacts, restClient);
+    verify(WireMock.putRequestedFor(urlEqualTo(
+        "/aai/v28/service-design-and-creation/models/model/modelInvariantId/model-vers/model-ver/modelVersionId")));
+    assertTrue(result);
+  }
+
+  @Test
+  public void thatModelCanBeRolledBack() {
+    stubFor(WireMock.get(urlEqualTo("/aai/v28/service-design-and-creation/models/model/3a40ab73-6694-4e75-bb6d-9a4a86ce35b3"))
+        .withHeader("X-FromAppId", equalTo("ModelLoader"))
+        .withHeader("X-TransactionId", equalTo("distributionId"))
+        .willReturn(aResponse()
+            .withBodyFile("modelResponse.xml")));
+
+    stubFor(WireMock.delete(urlEqualTo("/aai/v28/service-design-and-creation/models/model/3a40ab73-6694-4e75-bb6d-9a4a86ce35b3?resource-version=1710523260974"))
+        .withHeader("X-FromAppId", equalTo("ModelLoader"))
+        .withHeader("X-TransactionId", equalTo("distributionId"))
+        .willReturn(aResponse().withStatus(HttpStatus.OK.value())));
+
+    ModelArtifact modelArtifact = new ModelArtifact();
+    modelArtifact.setModelInvariantId("3a40ab73-6694-4e75-bb6d-9a4a86ce35b3");
+    modelArtifact.setModelVerId("modelVersionId");
+    Node node = Mockito.mock(Node.class);
+    modelArtifact.setModelVer(node);
+    List<Artifact> completedArtifacts = new ArrayList<>();
+    completedArtifacts.add(modelArtifact);
+
+    mockModelCreation(modelArtifact);
+
+    modelArtifactHandler.rollback(completedArtifacts, "distributionId", restClient);
+
+    verify(
+        deleteRequestedFor(
+            urlEqualTo("/aai/v28/service-design-and-creation/models/model/3a40ab73-6694-4e75-bb6d-9a4a86ce35b3?resource-version=1710523260974")));
+  }
+
+  /**
+   * To test the rollback of the full model, the ModelArtifact must have the
+   * firstVersionOfModel = true state.
+   * This flag is set during the model creation and thus needs to run before
+   * testing this particular aspect.
+   *
+   * @param modelArtifact
+   */
+  private void mockModelCreation(ModelArtifact modelArtifact) {
+    OperationResult createdResult = Mockito.mock(OperationResult.class);
+    when(createdResult.getResultCode()).thenReturn(HttpStatus.CREATED.value());
+    OperationResult notFoundResult = Mockito.mock(OperationResult.class);
+    when(notFoundResult.getResultCode()).thenReturn(HttpStatus.NOT_FOUND.value());
+    AaiRestClient aaiClient = Mockito.mock(AaiRestClient.class);
+    when(aaiClient.putResource(any(), any(), any(), any())).thenReturn(createdResult);
+    when(aaiClient.getResource(any(), any(), any())).thenReturn(notFoundResult);
+    modelArtifact.push(aaiClient, config, null, new ArrayList<>());
+  }
+
+  @Test
+  public void thatModelVersionCanBeRolledBack() {
+
+    // "http://localhost:10594/aai/v28/service-design-and-creation/models/model/modelInvariantId/model-vers/model-ver/modelVersionId"
+
+    ModelArtifact modelArtifact = new ModelArtifact();
+    modelArtifact.setModelInvariantId("modelInvariantId");
+    modelArtifact.setModelVerId("modelVersionId");
+    Node node = Mockito.mock(Node.class);
+    modelArtifact.setModelVer(node);
+    List<Artifact> completedArtifacts = new ArrayList<>();
+    completedArtifacts.add(modelArtifact);
+
+    modelArtifactHandler.rollback(completedArtifacts, "distributionId", restClient);
+
+  }
+}
\ No newline at end of file
diff --git a/src/test/java/org/onap/aai/modelloader/notification/TestNotificationDataImpl.java b/src/test/java/org/onap/aai/modelloader/notification/TestNotificationDataImpl.java
deleted file mode 100644
index 4d6858a..0000000
--- a/src/test/java/org/onap/aai/modelloader/notification/TestNotificationDataImpl.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/**
- * ============LICENSE_START=======================================================
- * org.onap.aai
- * ================================================================================
- * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
- * Copyright © 2017-2018 European Software Marketing Ltd.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *       http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-package org.onap.aai.modelloader.notification;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.not;
-import static org.hamcrest.MatcherAssert.assertThat;
-
-import org.junit.jupiter.api.Test;
-
-/**
- * Tests for NotificationDataImpl class
- *
- */
-public class TestNotificationDataImpl {
-
-    @Test
-    public void testGettersAndSetters() {
-        NotificationDataImpl data = new NotificationDataImpl();
-        String distributionId = "testid";
-
-        data.setDistributionID(distributionId);
-        assertThat(data.getDistributionID(), is(equalTo(distributionId)));
-
-        // Getters return empty data
-        assertThat(data.getArtifactMetadataByUUID(null), is(equalTo(null)));
-        assertThat(data.getServiceDescription(), is(equalTo(null)));
-        assertThat(data.getServiceInvariantUUID(), is(equalTo(null)));
-        assertThat(data.getServiceName(), is(equalTo(null)));
-        assertThat(data.getServiceUUID(), is(equalTo(null)));
-        assertThat(data.getServiceVersion(), is(equalTo(null)));
-        assertThat(data.getResources().size(), is(0));
-        assertThat(data.getServiceArtifacts().size(), is(0));
-
-        // Unsupported method!
-        String context = "testcontext";
-        data.setWorkloadContext(context);
-        assertThat(data.getWorkloadContext(), is(equalTo(null)));
-    }
-
-
-    @Test
-    public void testEquality() {
-        NotificationDataImpl data = new NotificationDataImpl();
-        assertThat(data, is(not(equalTo(null))));
-        assertThat(data, is(not(equalTo("")))); // NOSONAR
-        assertThat(data, is(equalTo(data)));
-
-        NotificationDataImpl other = new NotificationDataImpl();
-        assertThat(data, is(equalTo(other)));
-        assertThat(data.hashCode(), is(equalTo(other.hashCode())));
-
-        other.setDistributionID("");
-        assertThat(data, is(not(equalTo(other))));
-
-        data.setDistributionID("1234");
-        assertThat(data, is(not(equalTo(other))));
-
-        other.setDistributionID("1234");
-        assertThat(data, is(equalTo(other)));
-        assertThat(data.hashCode(), is(equalTo(other.hashCode())));
-    }
-
-}
diff --git a/src/test/java/org/onap/aai/modelloader/restclient/TestBabelServiceClient.java b/src/test/java/org/onap/aai/modelloader/restclient/TestBabelServiceClient.java
index 77e1594..169943c 100644
--- a/src/test/java/org/onap/aai/modelloader/restclient/TestBabelServiceClient.java
+++ b/src/test/java/org/onap/aai/modelloader/restclient/TestBabelServiceClient.java
@@ -20,68 +20,65 @@
  */
 package org.onap.aai.modelloader.restclient;
 
-import static javax.servlet.http.HttpServletResponse.SC_OK;
-import static org.apache.commons.io.IOUtils.write;
 import static org.hamcrest.CoreMatchers.equalTo;
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
 
 import java.io.IOException;
 import java.net.URISyntaxException;
-import java.nio.charset.Charset;
 import java.nio.file.Files;
 import java.nio.file.Paths;
-import java.util.ArrayList;
 import java.util.List;
 import java.util.Properties;
 
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.eclipse.jetty.server.Handler;
-import org.eclipse.jetty.server.Request;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.handler.AbstractHandler;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 import org.onap.aai.babel.service.data.BabelArtifact;
 import org.onap.aai.modelloader.config.ModelLoaderConfig;
 import org.onap.aai.modelloader.service.HttpsBabelServiceClientFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock;
 
-import com.google.gson.Gson;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.github.tomakehurst.wiremock.client.WireMock;
+import com.github.tomakehurst.wiremock.matching.EqualToPattern;
 
 /**
  * Local testing of the Babel service client.
  *
  */
+@SpringBootTest
+@AutoConfigureWireMock(port = 0)
 public class TestBabelServiceClient {
 
-    private Server server;
-    private String responseBody;
+    @Value("${wiremock.server.port}")
+    private int wiremockPort;
 
-    @BeforeEach
-    public void startJetty() throws Exception {
-        List<BabelArtifact> response = new ArrayList<>();
-        response.add(new BabelArtifact("", null, ""));
-        response.add(new BabelArtifact("", null, ""));
-        response.add(new BabelArtifact("", null, ""));
-        responseBody = new Gson().toJson(response);
-
-        server = new Server(0);
-        server.setHandler(getMockHandler());
-        server.start();
-    }
-
-    @AfterEach
-    public void stopJetty() throws Exception {
-        server.stop();
+    @BeforeAll
+    public static void setup() throws JsonProcessingException {
+        ObjectMapper objectMapper = new ObjectMapper();
+        List<BabelArtifact> artifacts = List.of(
+            new BabelArtifact("art1", null, ""),
+            new BabelArtifact("art2", null, ""),
+            new BabelArtifact("art3", null, ""));
+        WireMock.stubFor(
+            WireMock.post(WireMock.urlEqualTo("/generate"))
+                .withHeader("X-TransactionId", WireMock.equalTo("Test-Transaction-ID-BabelClient"))
+                .withHeader("X-FromAppId", WireMock.equalTo("ModelLoader"))
+                .withRequestBody(WireMock.matchingJsonPath("$.artifactName", WireMock.equalTo("service-Vscpass-Test")))
+                .withRequestBody(WireMock.matchingJsonPath("$.artifactVersion", WireMock.equalTo("1.0")))
+                .withRequestBody(WireMock.matchingJsonPath("$.csar", WireMock.matching(".*")))
+                .willReturn(
+                    WireMock.aResponse()
+                        .withHeader("Content-Type", "application/json")
+                        .withBody(objectMapper.writeValueAsString(artifacts))));
     }
 
     @Test
     public void testRestClient() throws BabelServiceClientException, IOException, URISyntaxException {
-        String url = server.getURI().toString();
+        String url = "http://localhost:" + wiremockPort;
         Properties configProperties = new Properties();
         configProperties.put("ml.babel.KEYSTORE_PASSWORD", "OBF:1vn21ugu1saj1v9i1v941sar1ugw1vo0");
         configProperties.put("ml.babel.KEYSTORE_FILE", "src/test/resources/auth/aai-client-dummy.p12");
@@ -89,7 +86,7 @@
         // In a real deployment this would be a different file (to the client keystore)
         configProperties.put("ml.babel.TRUSTSTORE_FILE", "src/test/resources/auth/aai-client-dummy.p12");
         configProperties.put("ml.babel.BASE_URL", url);
-        configProperties.put("ml.babel.GENERATE_ARTIFACTS_URL", "generate");
+        configProperties.put("ml.babel.GENERATE_ARTIFACTS_URL", "/generate");
         configProperties.put("ml.aai.RESTCLIENT_CONNECT_TIMEOUT", "12000");
         configProperties.put("ml.aai.RESTCLIENT_READ_TIMEOUT", "12000");
         BabelServiceClient client =
@@ -102,11 +99,11 @@
 
     @Test
     public void testRestClientHttp() throws BabelServiceClientException, IOException, URISyntaxException {
-        String url = server.getURI().toString();
+        String url = "http://localhost:" + wiremockPort;
         Properties configProperties = new Properties();
         configProperties.put("ml.babel.USE_HTTPS", "false");
         configProperties.put("ml.babel.BASE_URL", url);
-        configProperties.put("ml.babel.GENERATE_ARTIFACTS_URL", "generate");
+        configProperties.put("ml.babel.GENERATE_ARTIFACTS_URL", "/generate");
         configProperties.put("ml.aai.RESTCLIENT_CONNECT_TIMEOUT", "3000");
         configProperties.put("ml.aai.RESTCLIENT_READ_TIMEOUT", "3000");
         BabelServiceClient client =
@@ -121,23 +118,4 @@
     private byte[] readBytesFromFile(String resourceFile) throws IOException, URISyntaxException {
         return Files.readAllBytes(Paths.get(ClassLoader.getSystemResource(resourceFile).toURI()));
     }
-
-    /**
-     * Creates an {@link AbstractHandler handler} returning an arbitrary String as a response.
-     * 
-     * @return never <code>null</code>.
-     */
-    private Handler getMockHandler() {
-        Handler handler = new AbstractHandler() {
-            @Override
-            public void handle(String target, Request request, HttpServletRequest servletRequest,
-                    HttpServletResponse response) throws IOException, ServletException {
-                response.setStatus(SC_OK);
-                response.setContentType("text/xml;charset=utf-8");
-                write(responseBody, response.getOutputStream(), Charset.defaultCharset());
-                request.setHandled(true);
-            }
-        };
-        return handler;
-    }
 }
diff --git a/src/test/java/org/onap/aai/modelloader/restclient/TracingTest.java b/src/test/java/org/onap/aai/modelloader/restclient/TracingTest.java
new file mode 100644
index 0000000..3bfceb5
--- /dev/null
+++ b/src/test/java/org/onap/aai/modelloader/restclient/TracingTest.java
@@ -0,0 +1,63 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.aai
+ * ================================================================================
+ * Copyright © 2024 Deutsche Telekom AG Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.aai.modelloader.restclient;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.client.RestTemplate;
+
+import com.github.tomakehurst.wiremock.client.WireMock;
+
+@SpringBootTest(properties = {
+  "spring.sleuth.enabled=true",
+  "spring.zipkin.baseUrl=http://localhost:${wiremock.server.port}"
+})
+@AutoConfigureWireMock(port = 0)
+public class TracingTest {
+
+  @Value("${wiremock.server.port}")
+  private int wiremockPort;
+
+  @Autowired RestTemplate restTemplate;
+  
+  @Test
+  public void thatArtifactsCanBePushed() {
+    WireMock.stubFor(
+      WireMock.post(WireMock.urlEqualTo("/api/v2/spans"))
+          .willReturn(
+              WireMock.aResponse()
+                  .withStatus(HttpStatus.OK.value())));
+
+    WireMock.stubFor(
+      WireMock.get(WireMock.urlEqualTo("/"))
+          .withHeader("X-B3-TraceId", WireMock.matching(".*"))
+          .willReturn(
+              WireMock.aResponse()
+                  .withStatus(HttpStatus.OK.value())));
+
+
+    String response = restTemplate.getForObject("http://localhost:" + wiremockPort + "/", String.class);
+  }
+  
+}
diff --git a/src/test/java/org/onap/aai/modelloader/service/TestArtifactInfoImpl.java b/src/test/java/org/onap/aai/modelloader/service/TestArtifactInfoImpl.java
deleted file mode 100644
index d1d46f0..0000000
--- a/src/test/java/org/onap/aai/modelloader/service/TestArtifactInfoImpl.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/**
- * ============LICENSE_START=======================================================
- * org.onap.aai
- * ================================================================================
- * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
- * Copyright © 2017-2018 European Software Marketing Ltd.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *       http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-package org.onap.aai.modelloader.service;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.not;
-import static org.hamcrest.CoreMatchers.nullValue;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.empty;
-
-import org.junit.jupiter.api.Test;
-
-/**
- * Tests for NotificationDataImpl class
- *
- */
-public class TestArtifactInfoImpl {
-
-    @Test
-    public void testGettersAndSetters() {
-        ArtifactInfoImpl info = new ArtifactInfoImpl();
-        String artifactName = "testname";
-
-        info.setArtifactName(artifactName);
-        assertThat(info.getArtifactName(), is(equalTo(artifactName)));
-
-        String artifactType = "test-type";
-        info.setArtifactType(artifactType);
-        assertThat(info.getArtifactType(), is(equalTo(artifactType)));
-
-        String artifactVersion = "v1";
-        info.setArtifactVersion(artifactVersion);
-        assertThat(info.getArtifactVersion(), is(equalTo(artifactVersion)));
-
-        String artifactDescription = "test description";
-        info.setArtifactDescription(artifactDescription);
-        assertThat(info.getArtifactDescription(), is(equalTo(artifactDescription)));
-
-        assertThat(info.getArtifactChecksum(), is(nullValue()));
-        assertThat(info.getArtifactTimeout(), is(nullValue()));
-        assertThat(info.getArtifactURL(), is(nullValue()));
-        assertThat(info.getArtifactUUID(), is(nullValue()));
-        assertThat(info.getGeneratedArtifact(), is(nullValue()));
-        assertThat(info.getRelatedArtifacts(), is(empty()));
-    }
-
-
-    @Test
-    public void testEquality() {
-        ArtifactInfoImpl info = new ArtifactInfoImpl();
-        assertThat(info, is(not(equalTo(null))));
-        assertThat(info, is(not(equalTo("")))); // NOSONAR
-        assertThat(info, is(equalTo(info)));
-
-        ArtifactInfoImpl other = new ArtifactInfoImpl();
-        assertThat(info, is(equalTo(other)));
-        assertThat(info.hashCode(), is(equalTo(other.hashCode())));
-
-        // Artifact Name
-        other.setArtifactName("");
-        assertThat(info, is(not(equalTo(other))));
-
-        info.setArtifactName("1234");
-        assertThat(info, is(not(equalTo(other))));
-
-        other.setArtifactName("1234");
-        assertThat(info, is(equalTo(other)));
-        assertThat(info.hashCode(), is(equalTo(other.hashCode())));
-
-        // Artifact Type
-        other.setArtifactType("");
-        assertThat(info, is(not(equalTo(other))));
-
-        info.setArtifactType("type");
-        assertThat(info, is(not(equalTo(other))));
-
-        other.setArtifactType("type");
-        assertThat(info, is(equalTo(other)));
-        assertThat(info.hashCode(), is(equalTo(other.hashCode())));
-
-        // Artifact Description
-        other.setArtifactDescription("");
-        assertThat(info, is(not(equalTo(other))));
-
-        info.setArtifactDescription("type");
-        assertThat(info, is(not(equalTo(other))));
-
-        other.setArtifactDescription("type");
-        assertThat(info, is(equalTo(other)));
-        assertThat(info.hashCode(), is(equalTo(other.hashCode())));
-
-        // Artifact Version
-        other.setArtifactVersion("");
-        assertThat(info, is(not(equalTo(other))));
-
-        info.setArtifactVersion("v1");
-        assertThat(info, is(not(equalTo(other))));
-
-        other.setArtifactVersion("v1");
-        assertThat(info, is(equalTo(other)));
-        assertThat(info.hashCode(), is(equalTo(other.hashCode())));
-    }
-
-}
diff --git a/src/test/resources/__files/artifactTypes.json b/src/test/resources/__files/artifactTypes.json
new file mode 100644
index 0000000..de3cfce
--- /dev/null
+++ b/src/test/resources/__files/artifactTypes.json
@@ -0,0 +1,63 @@
+[
+  "AAI_SERVICE_MODEL",
+  "AAI_VF_INSTANCE_MODEL",
+  "AAI_VF_MODEL",
+  "AAI_VF_MODULE_MODEL",
+  "ANSIBLE_PLAYBOOK",
+  "APPC_CONFIG",
+  "BPEL",
+  "CHEF",
+  "CLOUD_TECHNOLOGY_SPECIFIC_ARTIFACT",
+  "CONTROLLER_BLUEPRINT_ARCHIVE",
+  "DCAE_DOC",
+  "DCAE_EVENT",
+  "DCAE_INVENTORY_BLUEPRINT",
+  "DCAE_INVENTORY_DOC",
+  "DCAE_INVENTORY_EVENT",
+  "DCAE_INVENTORY_JSON",
+  "DCAE_INVENTORY_POLICY",
+  "DCAE_INVENTORY_TOSCA",
+  "DCAE_JSON",
+  "DCAE_POLICY",
+  "DCAE_TOSCA",
+  "DG_XML",
+  "ETSI_PACKAGE",
+  "ASD_PACKAGE",
+  "GUIDE",
+  "HEAT_ARTIFACT",
+  "HEAT_ENV",
+  "HEAT",
+  "HEAT_NESTED",
+  "HEAT_NET",
+  "HEAT_VOL",
+  "HELM",
+  "ICON",
+  "LIFECYCLE_OPERATIONS",
+  "MODEL_INVENTORY_PROFILE",
+  "MODEL_QUERY_SPEC",
+  "MURANO_PKG",
+  "NETWORK_CALL_FLOW",
+  "ONBOARDED_PACKAGE",
+  "OTHER",
+  "PERFORMANCE_COUNTER",
+  "PLAN",
+  "PM_DICTIONARY",
+  "PNF_SW_INFORMATION",
+  "PUPPET",
+  "SHELL_SCRIPT",
+  "SHELL",
+  "SNMP_POLL",
+  "SNMP_TRAP",
+  "TOSCA_CSAR",
+  "TOSCA_TEMPLATE",
+  "UCPE_LAYER_2_CONFIGURATION",
+  "VENDOR_LICENSE",
+  "VES_EVENTS",
+  "VF_LICENSE",
+  "VF_MODULES_METADATA",
+  "VNF_CATALOG",
+  "WORKFLOW",
+  "YANG_MODULE",
+  "YANG_XML",
+  "YANG"
+]
\ No newline at end of file
diff --git a/src/test/resources/__files/kafkaBootstrap.json b/src/test/resources/__files/kafkaBootstrap.json
new file mode 100644
index 0000000..1820ade
--- /dev/null
+++ b/src/test/resources/__files/kafkaBootstrap.json
@@ -0,0 +1,5 @@
+{
+  "kafkaBootStrapServer": "localhost:9092",
+  "distrNotificationTopicName": "SDC-DISTR-NOTIF-TOPIC-AUTO",
+  "distrStatusTopicName": "SDC-DISTR-STATUS-TOPIC-AUTO"
+}
\ No newline at end of file
diff --git a/src/test/resources/__files/modelResponse.xml b/src/test/resources/__files/modelResponse.xml
new file mode 100644
index 0000000..36d07d8
--- /dev/null
+++ b/src/test/resources/__files/modelResponse.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<model xmlns="http://org.onap.aai.inventory/v28">
+  <model-invariant-id>3a40ab73-6694-4e75-bb6d-9a4a86ce35b3</model-invariant-id>
+  <model-type>service</model-type>
+  <model-role>Network Service</model-role>
+  <resource-version>1710523260974</resource-version>
+</model>
\ No newline at end of file
diff --git a/src/test/resources/__files/service-TestSvc-csar-babel-response.json b/src/test/resources/__files/service-TestSvc-csar-babel-response.json
new file mode 100644
index 0000000..7103156
--- /dev/null
+++ b/src/test/resources/__files/service-TestSvc-csar-babel-response.json
@@ -0,0 +1 @@
+[{"name":"AAI-test-svc-service-2.0.xml","type":"MODEL","payload":"<model xmlns=\"http://org.onap.aai.inventory/v28\">\n    <model-invariant-id>3c8bc8e7-e387-46ed-8616-70e99e2206dc</model-invariant-id>\n    <model-type>service</model-type>\n    <model-role>Network L1-3</model-role>\n    <model-vers>\n        <model-ver>\n            <model-version-id>71f47717-b100-4eac-940b-7d4e86a4cbb7</model-version-id>\n            <model-name>test-svc</model-name>\n            <model-version>2.0</model-version>\n            <model-description>test-svc</model-description>\n            <model-elements>\n                <model-element>\n                    <new-data-del-flag>T</new-data-del-flag>\n                    <cardinality>unbounded</cardinality>\n                    <model-elements/>\n                    <relationship-list>\n                        <relationship>\n                            <related-to>model-ver</related-to>\n                            <relationship-data>\n                                <relationship-key>model-ver.model-version-id</relationship-key>\n                                <relationship-value>46b92144-923a-4d20-b85a-3cbd847668a9</relationship-value>\n                            </relationship-data>\n                            <relationship-data>\n                                <relationship-key>model.model-invariant-id</relationship-key>\n                                <relationship-value>82194af1-3c2c-485a-8f44-420e22a9eaa4</relationship-value>\n                            </relationship-data>\n                        </relationship>\n                    </relationship-list>\n                </model-element>\n            </model-elements>\n        </model-ver>\n    </model-vers>\n</model>"}]
\ No newline at end of file
diff --git a/src/test/resources/__files/service-TestSvc-csar.csar b/src/test/resources/__files/service-TestSvc-csar.csar
new file mode 100644
index 0000000..711f068
--- /dev/null
+++ b/src/test/resources/__files/service-TestSvc-csar.csar
Binary files differ
diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties
index 96816ce..69f4ff7 100644
--- a/src/test/resources/application.properties
+++ b/src/test/resources/application.properties
@@ -1,10 +1,11 @@
 CONFIG_HOME=src/test/resources
 spring.kafka.consumer.auto-offset-reset=earliest
 spring.kafka.consumer.group-id=aai
-spring.kafka.consumer.client-id=aai-model-loader
-      
-test.topic=SDC-DISTR-NOTIF-TOPIC
+spring.kafka.consumer.client-id=aai-model-loader   
+topics.distribution.notification=SDC-DISTR-NOTIF-TOPIC-AUTO
 
 spring.sleuth.enabled=false
 
-ml.distribution.connection.enabled=false # avoid having the distribution client running in the background (requires active kafka)
\ No newline at end of file
+ml.distribution.connection.enabled=false # avoid having the distribution client running in the background (requires active kafka)
+
+spring.main.allow-bean-definition-overriding=true
\ No newline at end of file
diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml
index aef38e6..4bf73da 100644
--- a/src/test/resources/logback-test.xml
+++ b/src/test/resources/logback-test.xml
@@ -11,7 +11,7 @@
 		<appender-ref ref="STDOUT" />
 	</logger>
 
-	<root level="debug">
+	<root level="INFO">
 		<appender-ref ref="STDOUT" />
 	</root>
 </configuration>
diff --git a/src/test/resources/model-loader.properties b/src/test/resources/model-loader.properties
index 4c24679..2db7c09 100644
--- a/src/test/resources/model-loader.properties
+++ b/src/test/resources/model-loader.properties
@@ -1,16 +1,20 @@
 # Model Loader Distribution Client Configuration
 ml.distribution.ACTIVE_SERVER_TLS_AUTH=false
 ml.distribution.ASDC_ADDRESS=localhost:8443
+ml.distribution.ASDC_USE_HTTPS=false
 ml.distribution.CONSUMER_GROUP=aai-ml-group-test
 ml.distribution.CONSUMER_ID=aai-ml-id-test
-ml.distribution.ENVIRONMENT_NAME=env
+ml.distribution.ENVIRONMENT_NAME=AUTO
 ml.distribution.KEYSTORE_PASSWORD=
 ml.distribution.KEYSTORE_FILE=
 ml.distribution.PASSWORD=Aa123456
-ml.distribution.POLLING_INTERVAL=5
+ml.distribution.POLLING_INTERVAL=15
 ml.distribution.POLLING_TIMEOUT=3
 ml.distribution.USER=ci
 ml.distribution.ARTIFACT_TYPES=MODEL_QUERY_SPEC,TOSCA_CSAR
+ml.distribution.SASL_JAAS_CONFIG=org.apache.kafka.common.security.scram.ScramLoginModule required username="aai-modelloader-ku" password="somePassword";
+ml.distribution.SECURITY_PROTOCOL=PLAINTEXT
+ml.distribution.SASL_MECHANISM=PLAIN
 
 # Disable ASDC polling & enable REST interface
 ml.distribution.ASDC_CONNECTION_DISABLE=true