diff --git a/.vscode/settings.json b/.vscode/settings.json
index e0f15db..b72b3e1 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,3 +1,8 @@
{
- "java.configuration.updateBuildConfiguration": "automatic"
-}
\ No newline at end of file
+ "java.configuration.updateBuildConfiguration": "automatic",
+ "sonarlint.connectedMode.project": {
+ "connectionId": "LocalSonarQube",
+ "projectKey": "EasyDrop"
+ },
+ "java.debug.settings.onBuildFailureProceed": true
+}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 010c0fd..4daf9c2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,10 +1,34 @@
# Changelog
+## 0.2.0-SNAPSHOT
+
+### Added
+
+- `EbayItemDataSource` (#37)
+- `Product` class
+- Mapping between Product and its corresponding DTO
+- Dependencies: Lombok for easier notation, JUnit 5 Params for repetitive tests
+- Product Validation
+- Product Retrieval
+- Tests
+
+### Changed
+
+- `AbstractDataSource` between DataSource interface and implementations to minimize code duplication
+ - Affects AmazonProductDataSource and related tests (~ #39)
+- Testing resources moved to more intuitive location
+- Demo `Main` method now uses proper Product retrieval
+
+### Fixed
+
+- Logback configuration is now linked correctly
+- Config now properly adheres to singleton pattern
+
## 0.1.0
### Added
-- (DataSource) → AmazonProductDataSource as first external data source (#39)
-- ProductDTO as data holder structure for data from external sources (~ #39)
+- (DataSource) → `AmazonProductDataSource` as first external data source (#39)
+- `ProductDTO` as data holder structure for data from external sources (~ #39)
- Config for credential, base URLs etc. (~ #39)
- FormattingUtil for formatting price strings (~ #39)
diff --git a/SampleResponses/eBayProductAPISample.json b/SampleResponses/eBayProductAPISample.json
new file mode 100644
index 0000000..510288b
--- /dev/null
+++ b/SampleResponses/eBayProductAPISample.json
@@ -0,0 +1,133 @@
+{
+ "href": "https://api.ebay.com/buy/browse/v1/item_summary/search?q=drone&limit=1&offset=0",
+ "total": 260202,
+ "next": "https://api.ebay.com/buy/browse/v1/item_summary/search?q=drone&limit=1&offset=1",
+ "limit": 3,
+ "offset": 0,
+ "itemSummaries": [
+ {
+ "itemId": "v1|1**********1|0",
+ "title": "Syma X5SW-V3 Wifi FPV RC Drone Quadcopter 2.4Ghz 6-Axis Gyro with Headless Mode",
+ "leafCategoryIds": ["179697", "182186"],
+ "categories": [
+ {
+ "categoryId": "179697",
+ "categoryName": "Camera Drones"
+ },
+ {
+ "categoryId": "182186",
+ "categoryName": "Other RC Model Vehicles & Kits"
+ },
+ {
+ "categoryId": "2562",
+ "categoryName": "Radio Control & Control Line"
+ },
+ {
+ "categoryId": "220",
+ "categoryName": "Toys & Hobbies"
+ },
+ {
+ "categoryId": "625",
+ "categoryName": "Cameras & Photo"
+ },
+ {
+ "categoryId": "182181",
+ "categoryName": "RC Model Vehicles & Kits"
+ }
+ ],
+ "image": {
+ "imageUrl": "https://i.ebayimg.com/thumbs/images/g/n**************a/s-***5.jpg"
+ },
+ "price": {
+ "value": "59.99",
+ "currency": "USD"
+ },
+ "itemHref": "https://api.ebay.com/buy/browse/v1/item/v1******************0",
+ "seller": {
+ "username": "m********e",
+ "feedbackPercentage": "98.6",
+ "feedbackScore": 130000
+ },
+ "marketingPrice": {
+ "originalPrice": {
+ "value": "74.99",
+ "currency": "USD"
+ },
+ "discountPercentage": "20",
+ "discountAmount": {
+ "value": "15.00",
+ "currency": "USD"
+ },
+ "priceTreatment": "LIST_PRICE"
+ },
+ "condition": "New",
+ "conditionId": "1000",
+ "thumbnailImages": [
+ {
+ "imageUrl": "https://i.ebayimg.com/images/g/n**************a/s-l***0.jpg"
+ }
+ ],
+ "shippingOptions": [
+ {
+ "shippingCostType": "FIXED",
+ "shippingCost": {
+ "value": "0.00",
+ "currency": "USD"
+ },
+ "minEstimatedDeliveryDate": "2022-11-19T08:00:00.000Z",
+ "maxEstimatedDeliveryDate": "2022-11-21T08:00:00.000Z",
+ "guaranteedDelivery": true
+ }
+ ],
+ "buyingOptions": ["FIXED_PRICE", "BEST_OFFER"],
+ "itemAffiliateWebUrl": "https://www.ebay.com/itm/1**********1?hash=i************d*9",
+ "itemWebUrl": "https://www.ebay.com/itm/1**********1?hash=i************d*p",
+ "itemLocation": {
+ "postalCode": "0****",
+ "country": "US"
+ },
+ "additionalImages": [
+ {
+ "imageUrl": "https://origin-galleryplus.ebayimg.com/ws/web/1**********1_2_0_1/225x225.jpg"
+ },
+ {
+ "imageUrl": "https://origin-galleryplus.ebayimg.com/ws/web/1**********1_3_0_1/225x225.jpg"
+ },
+ {
+ "imageUrl": "https://origin-galleryplus.ebayimg.com/ws/web/1**********1_4_0_1/225x225.jpg"
+ },
+ {
+ "imageUrl": "https://origin-galleryplus.ebayimg.com/ws/web/1**********1_5_0_1/225x225.jpg"
+ },
+ {
+ "imageUrl": "https://origin-galleryplus.ebayimg.com/ws/web/1**********1_6_0_1/225x225.jpg"
+ },
+ {
+ "imageUrl": "https://origin-galleryplus.ebayimg.com/ws/web/1**********1_7_0_1/225x225.jpg"
+ },
+ {
+ "imageUrl": "https://origin-galleryplus.ebayimg.com/ws/web/1**********1_8_0_1/225x225.jpg"
+ },
+ {
+ "imageUrl": "https://origin-galleryplus.ebayimg.com/ws/web/1**********1_9_0_1/225x225.jpg"
+ },
+ {
+ "imageUrl": "https://origin-galleryplus.ebayimg.com/ws/web/1**********1_10_0_1/225x225.jpg"
+ },
+ {
+ "imageUrl": "https://origin-galleryplus.ebayimg.com/ws/web/1**********1_11_0_1/225x225.jpg"
+ },
+ {
+ "imageUrl": "https://origin-galleryplus.ebayimg.com/ws/web/1**********1_12_0_1/225x225.jpg"
+ }
+ ],
+ "adultOnly": false,
+ "legacyItemId": "1**********1",
+ "availableCoupons": false,
+ "itemCreationDate": "2022-12-25T07:14:44.000Z",
+ "topRatedBuyingExperience": true,
+ "priorityListing": true,
+ "listingMarketplaceId": "EBAY_US"
+ }
+ ]
+}
diff --git a/Script/SonarQube_Local.sh b/Script/SonarQube_Local.sh
new file mode 100644
index 0000000..18b0b37
--- /dev/null
+++ b/Script/SonarQube_Local.sh
@@ -0,0 +1,5 @@
+mvn clean verify sonar:sonar -Pcoverage \
+ -Dsonar.projectKey=EasyDrop \
+ -Dsonar.projectName='EasyDrop' \
+ -Dsonar.host.url=http://localhost:9000 \
+ -Dsonar.token=sqp_82d35689c620c15fd1064549375e17a2a5b0b931
\ No newline at end of file
diff --git a/config/demo.config.properties b/config/demo.config.properties
index fbb6e44..d3e4d63 100644
--- a/config/demo.config.properties
+++ b/config/demo.config.properties
@@ -1,3 +1,5 @@
# Amazon Credentials
AMAZON_API_URL=
-AMAZON_API_KEY=
\ No newline at end of file
+AMAZON_API_KEY=
+EBAY_API_URL=
+EBAY_API_KEY=
\ No newline at end of file
diff --git a/lombok.config b/lombok.config
new file mode 100644
index 0000000..a23edb4
--- /dev/null
+++ b/lombok.config
@@ -0,0 +1,2 @@
+config.stopBubbling = true
+lombok.addLombokGeneratedAnnotation = true
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 88f5f8e..0537059 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
de.rwu
easydrop
jar
- 0.1.0
+ 0.2.0-SNAPSHOT
EasyDrop
http://maven.apache.org
@@ -16,16 +16,29 @@
+
+ org.projectlombok
+ lombok
+ 1.18.28
+ provided
+
+
org.junit.jupiter
junit-jupiter-api
- 5.8.0
+ 5.9.3
test
org.junit.jupiter
junit-jupiter-engine
- 5.8.0
+ 5.9.3
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-params
+ 5.9.3
test
diff --git a/src/main/java/de/rwu/easydrop/Main.java b/src/main/java/de/rwu/easydrop/Main.java
index af1aeea..74b6aec 100644
--- a/src/main/java/de/rwu/easydrop/Main.java
+++ b/src/main/java/de/rwu/easydrop/Main.java
@@ -5,7 +5,8 @@ import javax.naming.ConfigurationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import de.rwu.easydrop.api.client.AmazonProductDataSource;
+import de.rwu.easydrop.api.client.DataSourceFactory;
+import de.rwu.easydrop.service.retriever.ProductRetriever;
import de.rwu.easydrop.util.Config;
/**
@@ -33,17 +34,12 @@ public final class Main {
*/
public static void main(final String[] args) throws ConfigurationException {
Config config = Config.getInstance();
- config.loadConfig();
- String amznBaseUrl = config.getProperty("AMAZON_API_URL");
- String amznApiKey = config.getProperty("AMAZON_API_KEY");
- String testProduct = null;
+ DataSourceFactory dataSourceFactory = new DataSourceFactory(config);
+ ProductRetriever retriever = new ProductRetriever(dataSourceFactory);
- AmazonProductDataSource amznSrc = new AmazonProductDataSource(amznBaseUrl, amznApiKey);
- try {
- testProduct = amznSrc.getProductDTOById("B096Y2TYKV").toString();
- LOGGER.info(testProduct);
- } catch (IllegalArgumentException e) {
- LOGGER.error("Something went wrong :(", e);
- }
+ String amznProduct = retriever.getProductFromAmazon("B096Y2TYKV").toString();
+ LOGGER.info(amznProduct);
+ String ebayProduct = retriever.getProductFromEbay("Gigabyte GeForce RTX 3060").toString();
+ LOGGER.info(ebayProduct);
}
}
diff --git a/src/main/java/de/rwu/easydrop/api/client/AbstractDataSource.java b/src/main/java/de/rwu/easydrop/api/client/AbstractDataSource.java
new file mode 100644
index 0000000..7751c10
--- /dev/null
+++ b/src/main/java/de/rwu/easydrop/api/client/AbstractDataSource.java
@@ -0,0 +1,100 @@
+package de.rwu.easydrop.api.client;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import de.rwu.easydrop.api.dto.ProductDTO;
+import de.rwu.easydrop.exception.DataSourceException;
+import de.rwu.easydrop.util.FormattingUtil;
+
+/**
+ * Helper class for shared data and functions between data sources.
+ *
+ * @since 0.2.0
+ */
+public abstract class AbstractDataSource implements DataSource {
+
+ /**
+ * Returns the data origin for the current source.
+ *
+ * @return Data source name
+ */
+ protected abstract String getDataOrigin();
+
+ /**
+ * Returns the data source's API key.
+ *
+ * @return Data source API key
+ */
+ protected abstract String getApiKey();
+
+ /**
+ * Enriches a ProductDTO with API-gathered data.
+ *
+ * @param product Unfinished ProductDTO
+ * @param json Product data
+ * @return Finished ProductDTO
+ */
+ protected abstract ProductDTO buildProductDTO(ProductDTO product, String json);
+
+ /**
+ * Overridable standard implementation.
+ */
+ @Override
+ public ProductDTO getProductDTOById(final String productIdentifier)
+ throws IllegalArgumentException {
+ StringBuilder response = new StringBuilder();
+ String dataOrigin = getDataOrigin();
+ String apiKey = getApiKey();
+ ProductDTO product = new ProductDTO(productIdentifier, dataOrigin);
+
+ try {
+ String urlReadyIdentifier = FormattingUtil.urlEncode(productIdentifier);
+ URL apiUrl = createApiUrl(urlReadyIdentifier);
+
+ HttpURLConnection connection = (HttpURLConnection) apiUrl.openConnection();
+ connection.setRequestMethod("GET");
+ connection.setRequestProperty("Credential", apiKey);
+
+ int responseCode = connection.getResponseCode();
+ BufferedReader reader;
+ if (responseCode == HttpURLConnection.HTTP_OK) {
+ reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
+ } else {
+ throw new DataSourceException(
+ "Nothing found: "
+ + dataOrigin
+ + " API responded with error code "
+ + responseCode);
+ }
+
+ String line;
+ while ((line = reader.readLine()) != null) {
+ response.append(line);
+ }
+ reader.close();
+
+ buildProductDTO(product, response.toString());
+ } catch (IOException e) {
+ throw new DataSourceException(
+ "Couldn't fulfill "
+ + dataOrigin
+ + " API request");
+ }
+
+ return product;
+ }
+
+ /**
+ * Creates an URL object to connect to the API with.
+ *
+ * @param productIdentifier Product identifier
+ * @return URL object
+ * @throws MalformedURLException
+ */
+ protected abstract URL createApiUrl(String productIdentifier) throws MalformedURLException;
+}
diff --git a/src/main/java/de/rwu/easydrop/api/client/AmazonProductDataSource.java b/src/main/java/de/rwu/easydrop/api/client/AmazonProductDataSource.java
index dbbdc6d..83b758d 100644
--- a/src/main/java/de/rwu/easydrop/api/client/AmazonProductDataSource.java
+++ b/src/main/java/de/rwu/easydrop/api/client/AmazonProductDataSource.java
@@ -1,9 +1,5 @@
package de.rwu.easydrop.api.client;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
@@ -18,7 +14,7 @@ import de.rwu.easydrop.api.dto.ProductDTO;
*
* @since 0.1.0
*/
-public final class AmazonProductDataSource implements DataSource {
+public final class AmazonProductDataSource extends AbstractDataSource {
/**
* Name of this data source.
*/
@@ -28,7 +24,7 @@ public final class AmazonProductDataSource implements DataSource {
*/
private String baseUrl;
/**
- * Credential key to authorize acccess.
+ * Credential key to authorize access.
*/
private String apiKey;
/**
@@ -52,48 +48,7 @@ public final class AmazonProductDataSource implements DataSource {
}
@Override
- public ProductDTO getProductDTOById(final String productId) throws IllegalArgumentException {
- StringBuilder response = new StringBuilder();
- ProductDTO product = new ProductDTO(productId, DATA_ORIGIN);
-
- try {
- URL apiUrl = createApiUrl(productId);
-
- HttpURLConnection connection = (HttpURLConnection) apiUrl.openConnection();
- connection.setRequestMethod("GET");
- connection.setRequestProperty("Credential", apiKey);
-
- int responseCode = connection.getResponseCode();
- BufferedReader reader;
- if (responseCode == HttpURLConnection.HTTP_OK) {
- reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
- } else {
- throw new IllegalArgumentException(
- "Nothing found: Amazon API responded with error code " + responseCode);
- }
-
- String line;
- while ((line = reader.readLine()) != null) {
- response.append(line);
- }
- reader.close();
-
- buildProductDTO(product, response.toString());
- } catch (IOException e) {
- throw new IllegalArgumentException("Couldn't fulfill Amazon API request");
- }
-
- return product;
- }
-
- /**
- * Enriches a ProductDTO with API-gathered data.
- *
- * @param product Unfinished ProductDTO
- * @param json Product data
- * @return Finished ProductDTO
- */
- public ProductDTO buildProductDTO(final ProductDTO product, final String json) {
+ protected ProductDTO buildProductDTO(final ProductDTO product, final String json) {
String root = "$.featuredOffer.";
ReadContext ctx = JsonPath.parse(json);
@@ -112,8 +67,11 @@ public final class AmazonProductDataSource implements DataSource {
return product;
}
+ /**
+ * @param productId ASIN
+ */
@Override
- public URL createApiUrl(final String productId) throws MalformedURLException {
+ protected URL createApiUrl(final String productId) throws MalformedURLException {
return new URL(baseUrl
+ "/products/2020-08-26/products/"
+ productId
@@ -122,4 +80,14 @@ public final class AmazonProductDataSource implements DataSource {
+ "&locale="
+ LOCALE);
}
+
+ @Override
+ protected String getDataOrigin() {
+ return DATA_ORIGIN;
+ }
+
+ @Override
+ protected String getApiKey() {
+ return this.apiKey;
+ }
}
diff --git a/src/main/java/de/rwu/easydrop/api/client/DataSource.java b/src/main/java/de/rwu/easydrop/api/client/DataSource.java
index 7b1c4e7..bda028f 100644
--- a/src/main/java/de/rwu/easydrop/api/client/DataSource.java
+++ b/src/main/java/de/rwu/easydrop/api/client/DataSource.java
@@ -1,8 +1,5 @@
package de.rwu.easydrop.api.client;
-import java.net.MalformedURLException;
-import java.net.URL;
-
import de.rwu.easydrop.api.dto.ProductDTO;
/**
@@ -12,17 +9,8 @@ public interface DataSource {
/**
* Retrieves product info from the data source.
*
- * @param productId ASIN
+ * @param productIdentifier Product identifier
* @return ProductDTO
*/
- ProductDTO getProductDTOById(String productId);
-
- /**
- * Creates an URL object to connect to the API with.
- *
- * @param productId ASIN
- * @return URL object
- * @throws MalformedURLException
- */
- URL createApiUrl(String productId) throws MalformedURLException;
+ ProductDTO getProductDTOById(String productIdentifier);
}
diff --git a/src/main/java/de/rwu/easydrop/api/client/DataSourceFactory.java b/src/main/java/de/rwu/easydrop/api/client/DataSourceFactory.java
new file mode 100644
index 0000000..ba79ab5
--- /dev/null
+++ b/src/main/java/de/rwu/easydrop/api/client/DataSourceFactory.java
@@ -0,0 +1,55 @@
+package de.rwu.easydrop.api.client;
+
+import javax.naming.ConfigurationException;
+
+import de.rwu.easydrop.util.Config;
+
+/**
+ * Factory for Data Sources.
+ *
+ * @since 0.2.0
+ */
+public class DataSourceFactory {
+
+ /**
+ * The data source config.
+ */
+ private Config config;
+
+ /**
+ * @param newConfig the config to set
+ */
+ public void setConfig(final Config newConfig) throws ConfigurationException {
+ this.config = newConfig;
+ this.config.loadConfig();
+ }
+
+ /**
+ * @param newConfig
+ */
+ public DataSourceFactory(final Config newConfig) throws ConfigurationException {
+ this.setConfig(newConfig);
+ }
+
+ /**
+ * Creates an Amazon Product Data Source.
+ *
+ * @return AmazonProductDataSource
+ */
+ public AmazonProductDataSource createAmazonProductDataSource() {
+ String apiUrl = config.getProperty("AMAZON_API_URL");
+ String apiKey = config.getProperty("AMAZON_API_KEY");
+ return new AmazonProductDataSource(apiUrl, apiKey);
+ }
+
+ /**
+ * Creates an eBay Item Data Source.
+ *
+ * @return EbayItemDataSource
+ */
+ public EbayItemDataSource createEbayItemDataSource() {
+ String apiUrl = config.getProperty("EBAY_API_URL");
+ String apiKey = config.getProperty("EBAY_API_KEY");
+ return new EbayItemDataSource(apiUrl, apiKey);
+ }
+}
diff --git a/src/main/java/de/rwu/easydrop/api/client/EbayItemDataSource.java b/src/main/java/de/rwu/easydrop/api/client/EbayItemDataSource.java
new file mode 100644
index 0000000..171b8b9
--- /dev/null
+++ b/src/main/java/de/rwu/easydrop/api/client/EbayItemDataSource.java
@@ -0,0 +1,88 @@
+package de.rwu.easydrop.api.client;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import com.jayway.jsonpath.JsonPath;
+import com.jayway.jsonpath.PathNotFoundException;
+import com.jayway.jsonpath.ReadContext;
+
+import de.rwu.easydrop.api.dto.ProductDTO;
+
+/**
+ * Interface to an eBay data source.
+ *
+ * @since 0.2.0
+ */
+public final class EbayItemDataSource extends AbstractDataSource {
+ /**
+ * Name of this data source.
+ */
+ private static final String DATA_ORIGIN = "eBay";
+ /**
+ * Base URL to the eBay data source.
+ */
+ private String baseUrl;
+ /**
+ * Credential key to authorize access.
+ */
+ private String apiKey;
+
+ /**
+ * Sets up instance with Base URL and API Key.
+ *
+ * @param newBaseUrl
+ * @param newApiKey
+ */
+ public EbayItemDataSource(final String newBaseUrl, final String newApiKey) {
+ this.baseUrl = newBaseUrl;
+ this.apiKey = newApiKey;
+ }
+
+ /**
+ * @param searchQuery Exact product name or other valid identifier.
+ */
+ @Override
+ protected URL createApiUrl(final String searchQuery) throws MalformedURLException {
+ return new URL(baseUrl
+ + "/buy/browse/v1/item_summary/search?q="
+ + searchQuery
+ + "&limit=1&offset=0");
+ }
+
+ /**
+ * Enriches a ProductDTO with API-gathered data.
+ *
+ * @param product Unfinished ProductDTO
+ * @param json Product data
+ * @return Finished ProductDTO
+ */
+ protected ProductDTO buildProductDTO(final ProductDTO product, final String json) {
+ String root = "$.itemSummaries[0].";
+ ReadContext ctx = JsonPath.parse(json);
+
+ try {
+ product.setDataOrigin(DATA_ORIGIN);
+ product.setAvailable(
+ ctx.read(root + "shippingOptions[0].guaranteedDelivery", boolean.class));
+ product.setCurrentPrice(ctx.read(root + "price.value", double.class));
+ product.setDeliveryPrice(
+ ctx.read(root + "shippingOptions[0].shippingCost.value", double.class));
+ product.setMerchant(ctx.read(root + "seller.username", String.class));
+ } catch (PathNotFoundException e) {
+ // Pass, allow incomplete ProductDTO to pass for later validation
+ }
+
+ return product;
+ }
+
+ @Override
+ protected String getDataOrigin() {
+ return DATA_ORIGIN;
+ }
+
+ @Override
+ protected String getApiKey() {
+ return this.apiKey;
+ }
+}
diff --git a/src/main/java/de/rwu/easydrop/api/dto/ProductDTO.java b/src/main/java/de/rwu/easydrop/api/dto/ProductDTO.java
index e3a706c..f6beb85 100644
--- a/src/main/java/de/rwu/easydrop/api/dto/ProductDTO.java
+++ b/src/main/java/de/rwu/easydrop/api/dto/ProductDTO.java
@@ -1,139 +1,52 @@
package de.rwu.easydrop.api.dto;
-import de.rwu.easydrop.util.FormattingUtil;
+import lombok.Data;
/**
* Product data transfer object.
*
* @since 0.1.0
*/
+@Data
public class ProductDTO {
/**
* Data source platform, like "Amazon".
*/
private String dataOrigin;
- /**
- * @return the dataOrigin
- */
- public String getDataOrigin() {
- return dataOrigin;
- }
-
- /**
- * @param newDataOrigin the dataOrigin to set
- */
- public void setDataOrigin(final String newDataOrigin) {
- this.dataOrigin = newDataOrigin;
- }
-
/**
* Platform internal product identifier.
*/
private String productId;
- /**
- * @return the productId
- */
- public String getProductId() {
- return productId;
- }
-
/**
* Current product price per piece in Euro.
*/
private double currentPrice;
- /**
- * @return the currentPrice
- */
- public double getCurrentPrice() {
- return currentPrice;
- }
-
- /**
- * @param newCurrentPrice the currentPrice to set
- */
- public void setCurrentPrice(final double newCurrentPrice) {
- this.currentPrice = newCurrentPrice;
- }
-
/**
* Name of mercant offering the product on the platform.
*/
private String merchant;
- /**
- * @return the merchant
- */
- public String getMerchant() {
- return merchant;
- }
-
- /**
- * @param newMerchant the merchant to set
- */
- public void setMerchant(final String newMerchant) {
- this.merchant = newMerchant;
- }
-
/**
* Additional Cost for delivery in Euro.
*/
private double deliveryPrice;
- /**
- * @return the deliveryPrice
- */
- public double getDeliveryPrice() {
- return deliveryPrice;
- }
-
- /**
- * @param newDeliveryPrice the deliveryPrice to set
- */
- public void setDeliveryPrice(final double newDeliveryPrice) {
- this.deliveryPrice = newDeliveryPrice;
- }
-
/**
* Whether the product can be purchased at this point.
*/
private boolean available;
- /**
- * @return the available
- */
- public boolean isAvailable() {
- return available;
- }
-
- /**
- * @param newAvailable the available to set
- */
- public void setAvailable(final boolean newAvailable) {
- this.available = newAvailable;
- }
-
/**
* Creates ProductDTO instance.
*
- * @param newProductId Interal Product indetifier
+ * @param newProductId Internal Product indetifier
* @param newDataOrigin Data Origin
*/
public ProductDTO(final String newProductId, final String newDataOrigin) {
this.productId = newProductId;
this.dataOrigin = newDataOrigin;
}
-
- @Override
- public final String toString() {
- return "ProductDTO{"
- + productId + " from "
- + merchant + " ("
- + dataOrigin + ")"
- + " at "
- + FormattingUtil.formatEuro(currentPrice) + " (available: "
- + (available ? "yes" : "no") + ")}";
- }
}
diff --git a/src/main/java/de/rwu/easydrop/data/model/Product.java b/src/main/java/de/rwu/easydrop/data/model/Product.java
deleted file mode 100644
index cfee872..0000000
--- a/src/main/java/de/rwu/easydrop/data/model/Product.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package de.rwu.easydrop.data.model;
-
-/**
- * A Product.
- *
- * TODO implement
- */
-public class Product {
-
-}
diff --git a/src/main/java/de/rwu/easydrop/data/model/package-info.java b/src/main/java/de/rwu/easydrop/data/model/package-info.java
deleted file mode 100644
index f33ce31..0000000
--- a/src/main/java/de/rwu/easydrop/data/model/package-info.java
+++ /dev/null
@@ -1,6 +0,0 @@
-/**
- * Business objects.
- *
- * TODO implement
- */
-package de.rwu.easydrop.data.model;
diff --git a/src/main/java/de/rwu/easydrop/exception/DataSourceException.java b/src/main/java/de/rwu/easydrop/exception/DataSourceException.java
new file mode 100644
index 0000000..0bca4d8
--- /dev/null
+++ b/src/main/java/de/rwu/easydrop/exception/DataSourceException.java
@@ -0,0 +1,27 @@
+package de.rwu.easydrop.exception;
+
+/**
+ * Exception that signifies the data of a Product are invalid.
+ *
+ * @since 0.2.0
+ */
+public class DataSourceException extends RuntimeException {
+ /**
+ * Throws an exception that signifies the data of a Product are invalid.
+ *
+ * @param message
+ */
+ public DataSourceException(final String message) {
+ super(message);
+ }
+
+ /**
+ * Throws an exception that signifies the data of a Product are invalid.
+ *
+ * @param message
+ * @param cause
+ */
+ public DataSourceException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/src/main/java/de/rwu/easydrop/exception/InvalidProductException.java b/src/main/java/de/rwu/easydrop/exception/InvalidProductException.java
new file mode 100644
index 0000000..d42ba39
--- /dev/null
+++ b/src/main/java/de/rwu/easydrop/exception/InvalidProductException.java
@@ -0,0 +1,27 @@
+package de.rwu.easydrop.exception;
+
+/**
+ * Exception that signifies the data of a Product are invalid.
+ *
+ * @since 0.2.0
+ */
+public class InvalidProductException extends RuntimeException {
+ /**
+ * Throws an exception that signifies the data of a Product are invalid.
+ *
+ * @param message
+ */
+ public InvalidProductException(final String message) {
+ super(message);
+ }
+
+ /**
+ * Throws an exception that signifies the data of a Product are invalid.
+ *
+ * @param message
+ * @param cause
+ */
+ public InvalidProductException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/src/main/java/de/rwu/easydrop/exception/package-info.java b/src/main/java/de/rwu/easydrop/exception/package-info.java
new file mode 100644
index 0000000..327d7d1
--- /dev/null
+++ b/src/main/java/de/rwu/easydrop/exception/package-info.java
@@ -0,0 +1,6 @@
+/**
+ * Contains EasyDrop-related custom exceptions.
+ *
+ * @since 0.2.0
+ */
+package de.rwu.easydrop.exception;
diff --git a/src/main/java/de/rwu/easydrop/model/Product.java b/src/main/java/de/rwu/easydrop/model/Product.java
new file mode 100644
index 0000000..1e5b3b2
--- /dev/null
+++ b/src/main/java/de/rwu/easydrop/model/Product.java
@@ -0,0 +1,53 @@
+package de.rwu.easydrop.model;
+
+import de.rwu.easydrop.util.FormattingUtil;
+import lombok.Data;
+
+/**
+ * A Product.
+ *
+ * @since 0.2.0
+ */
+@Data
+public class Product {
+ /**
+ * Data source platform, like "Amazon".
+ */
+ private String dataOrigin;
+
+ /**
+ * Platform internal product identifier.
+ */
+ private String productId;
+
+ /**
+ * Current product price per piece in Euro.
+ */
+ private double currentPrice;
+
+ /**
+ * Name of mercant offering the product on the platform.
+ */
+ private String merchant;
+
+ /**
+ * Additional Cost for delivery in Euro.
+ */
+ private double deliveryPrice;
+
+ /**
+ * Whether the product can be purchased at this point.
+ */
+ private boolean available;
+
+ @Override
+ public final String toString() {
+ return "Product: ["
+ + productId + " from "
+ + merchant + " ("
+ + dataOrigin + ")"
+ + " at "
+ + FormattingUtil.formatEuro(currentPrice) + " (available: "
+ + (available ? "yes" : "no") + ")]";
+ }
+}
diff --git a/src/main/java/de/rwu/easydrop/model/package-info.java b/src/main/java/de/rwu/easydrop/model/package-info.java
new file mode 100644
index 0000000..0c255df
--- /dev/null
+++ b/src/main/java/de/rwu/easydrop/model/package-info.java
@@ -0,0 +1,6 @@
+/**
+ * Business objects.
+ *
+ * @since 0.2.0
+ */
+package de.rwu.easydrop.model;
diff --git a/src/main/java/de/rwu/easydrop/service/mapping/ProductMapper.java b/src/main/java/de/rwu/easydrop/service/mapping/ProductMapper.java
index 5d4a6d3..1b37a11 100644
--- a/src/main/java/de/rwu/easydrop/service/mapping/ProductMapper.java
+++ b/src/main/java/de/rwu/easydrop/service/mapping/ProductMapper.java
@@ -1,14 +1,44 @@
package de.rwu.easydrop.service.mapping;
+import de.rwu.easydrop.api.dto.ProductDTO;
+import de.rwu.easydrop.model.Product;
+
/**
* Maps between Product, ProductDAO and ProductDTO.
*
- * TODO implement
+ * @since 0.2.0
*
* @see Product
* @see ProductDTO
* @see ProductDAO
*/
-public class ProductMapper {
+public final class ProductMapper {
+ /**
+ * Private constructor to prevent unwanted instantiation.
+ *
+ * @throws UnsupportedOperationException always
+ */
+ private ProductMapper() throws UnsupportedOperationException {
+ throw new UnsupportedOperationException("This is a mapping class, don't instantiate it.");
+ }
+
+ /**
+ * Creates a Product object from a corresponding DTO.
+ *
+ * @param dto Product Data Transfer Object
+ * @return Product
+ */
+ public static Product mapProductFromDTO(final ProductDTO dto) {
+ Product product = new Product();
+
+ product.setAvailable(dto.isAvailable());
+ product.setCurrentPrice(dto.getCurrentPrice());
+ product.setDataOrigin(dto.getDataOrigin());
+ product.setDeliveryPrice(dto.getDeliveryPrice());
+ product.setMerchant(dto.getMerchant());
+ product.setProductId(dto.getProductId());
+
+ return product;
+ }
}
diff --git a/src/main/java/de/rwu/easydrop/service/mapping/package-info.java b/src/main/java/de/rwu/easydrop/service/mapping/package-info.java
index ab86051..944f66d 100644
--- a/src/main/java/de/rwu/easydrop/service/mapping/package-info.java
+++ b/src/main/java/de/rwu/easydrop/service/mapping/package-info.java
@@ -1,6 +1,6 @@
/**
* Maps different formats of corresponding objects.
*
- * TODO implement
+ * @since 0.2.0
*/
package de.rwu.easydrop.service.mapping;
diff --git a/src/main/java/de/rwu/easydrop/service/retriever/ProductRetriever.java b/src/main/java/de/rwu/easydrop/service/retriever/ProductRetriever.java
new file mode 100644
index 0000000..bce5d10
--- /dev/null
+++ b/src/main/java/de/rwu/easydrop/service/retriever/ProductRetriever.java
@@ -0,0 +1,67 @@
+package de.rwu.easydrop.service.retriever;
+
+import de.rwu.easydrop.api.client.AmazonProductDataSource;
+import de.rwu.easydrop.api.client.DataSourceFactory;
+import de.rwu.easydrop.api.client.EbayItemDataSource;
+import de.rwu.easydrop.api.dto.ProductDTO;
+import de.rwu.easydrop.model.Product;
+import de.rwu.easydrop.service.mapping.ProductMapper;
+import de.rwu.easydrop.service.validation.ProductValidator;
+
+/**
+ * Retrieves Product Objects from various data sources.
+ *
+ * @since 0.2.0
+ */
+public class ProductRetriever {
+ /**
+ * Data source factory.
+ */
+ private DataSourceFactory dataSourceFactory;
+
+ /**
+ * @param newDataSourceFactory the dataSourceFactory to set
+ */
+ public void setDataSourceFactory(final DataSourceFactory newDataSourceFactory) {
+ this.dataSourceFactory = newDataSourceFactory;
+ }
+
+ /**
+ * @param newDataSourceFactory
+ */
+ public ProductRetriever(final DataSourceFactory newDataSourceFactory) {
+ this.setDataSourceFactory(newDataSourceFactory);
+ }
+
+ /**
+ * Retrieves a product from Amazon.
+ *
+ * @param asin Product identifier
+ * @return Product from Amazon
+ */
+ public Product getProductFromAmazon(final String asin) {
+ AmazonProductDataSource dataSource = dataSourceFactory.createAmazonProductDataSource();
+ ProductDTO dto = dataSource.getProductDTOById(asin);
+
+ Product product = ProductMapper.mapProductFromDTO(dto);
+ ProductValidator.validate(product);
+
+ return product;
+ }
+
+ /**
+ * Retrieves a product from eBay.
+ *
+ * @param query Product search query
+ * @return Product from eBay
+ */
+ public Product getProductFromEbay(final String query) {
+ EbayItemDataSource dataSource = dataSourceFactory.createEbayItemDataSource();
+ ProductDTO dto = dataSource.getProductDTOById(query);
+
+ Product product = ProductMapper.mapProductFromDTO(dto);
+ ProductValidator.validate(product);
+
+ return product;
+ }
+}
diff --git a/src/main/java/de/rwu/easydrop/service/retriever/package-info.java b/src/main/java/de/rwu/easydrop/service/retriever/package-info.java
new file mode 100644
index 0000000..f412441
--- /dev/null
+++ b/src/main/java/de/rwu/easydrop/service/retriever/package-info.java
@@ -0,0 +1,6 @@
+/**
+ * Retrieves Objects from a data source.
+ *
+ * @since 0.2.0
+ */
+package de.rwu.easydrop.service.retriever;
diff --git a/src/main/java/de/rwu/easydrop/service/validation/ProductValidator.java b/src/main/java/de/rwu/easydrop/service/validation/ProductValidator.java
index 3c93108..fc48377 100644
--- a/src/main/java/de/rwu/easydrop/service/validation/ProductValidator.java
+++ b/src/main/java/de/rwu/easydrop/service/validation/ProductValidator.java
@@ -1,10 +1,56 @@
package de.rwu.easydrop.service.validation;
+import java.util.HashSet;
+import java.util.Set;
+
+import de.rwu.easydrop.exception.InvalidProductException;
+import de.rwu.easydrop.model.Product;
+
/**
* Confirms validity of Product data.
*
- * @since 0.1.0
+ * @since 0.2.0
*/
-public class ProductValidator {
+public final class ProductValidator {
+ /**
+ * Private constructor to prevent unwanted instantiation.
+ *
+ * @throws UnsupportedOperationException always
+ */
+ private ProductValidator() throws UnsupportedOperationException {
+ throw new UnsupportedOperationException("This is a validator class, don't instantiate it.");
+ }
+
+ /**
+ * Makes sure a Product does not contain invalid information.
+ *
+ * @param product the Product
+ */
+ public static void validate(final Product product) {
+ if (product.getCurrentPrice() == 0.00) {
+ throw new InvalidProductException("Current price cannot be 0.00");
+ }
+ if (!isInValidDataOrigins(product.getDataOrigin())) {
+ throw new InvalidProductException("Unknown data source");
+ }
+ if (product.getProductId().equals("")) {
+ throw new InvalidProductException("Product ID cannot be empty");
+ }
+ }
+
+ /**
+ * Checks whether a dataOrigin is within the set of valid ones.
+ *
+ * @param dataOrigin like "Amazon"
+ * @return true if valid
+ */
+ public static boolean isInValidDataOrigins(final String dataOrigin) {
+ Set validOrigins = new HashSet<>();
+
+ validOrigins.add("Amazon");
+ validOrigins.add("eBay");
+
+ return validOrigins.contains(dataOrigin);
+ }
}
diff --git a/src/main/java/de/rwu/easydrop/service/validation/package-info.java b/src/main/java/de/rwu/easydrop/service/validation/package-info.java
index 6b45561..a74f45c 100644
--- a/src/main/java/de/rwu/easydrop/service/validation/package-info.java
+++ b/src/main/java/de/rwu/easydrop/service/validation/package-info.java
@@ -1,6 +1,6 @@
/**
* Supports validation processes.
*
- * TODO implement
+ * @since 0.2.0
*/
package de.rwu.easydrop.service.validation;
diff --git a/src/main/java/de/rwu/easydrop/util/Config.java b/src/main/java/de/rwu/easydrop/util/Config.java
index 7a7f1e3..32cce6a 100644
--- a/src/main/java/de/rwu/easydrop/util/Config.java
+++ b/src/main/java/de/rwu/easydrop/util/Config.java
@@ -56,7 +56,7 @@ public final class Config {
*/
public static Config getInstance() {
if (instance == null) {
- return new Config();
+ instance = new Config();
}
return instance;
@@ -109,4 +109,11 @@ public final class Config {
public void setProperty(final String key, final String value) {
properties.setProperty(key, value);
}
+
+ /**
+ * Resets the config's properties.
+ */
+ public void reset() {
+ properties = null;
+ }
}
diff --git a/src/main/java/de/rwu/easydrop/util/FormattingUtil.java b/src/main/java/de/rwu/easydrop/util/FormattingUtil.java
index 283e506..7ef0e69 100644
--- a/src/main/java/de/rwu/easydrop/util/FormattingUtil.java
+++ b/src/main/java/de/rwu/easydrop/util/FormattingUtil.java
@@ -27,4 +27,14 @@ public final class FormattingUtil {
public static String formatEuro(final double amount) {
return String.format(Locale.GERMAN, "%,.2f", amount) + " €";
}
+
+ /**
+ * Makes a string URL ready. For now, only spaces are replaced.
+ *
+ * @param str
+ * @return URL-ready string
+ */
+ public static String urlEncode(final String str) {
+ return str.replace(" ", "+");
+ }
}
diff --git a/config/logback.xml b/src/main/resources/logback.xml
similarity index 80%
rename from config/logback.xml
rename to src/main/resources/logback.xml
index 6b610a9..a2b1b43 100644
--- a/config/logback.xml
+++ b/src/main/resources/logback.xml
@@ -1,4 +1,6 @@
+
+
%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
@@ -6,7 +8,7 @@
-
+
\ No newline at end of file
diff --git a/src/test/java/de/rwu/easydrop/api/client/AmazonProductDataSourceTest.java b/src/test/java/de/rwu/easydrop/api/client/AmazonProductDataSourceTest.java
index 032d682..938413d 100644
--- a/src/test/java/de/rwu/easydrop/api/client/AmazonProductDataSourceTest.java
+++ b/src/test/java/de/rwu/easydrop/api/client/AmazonProductDataSourceTest.java
@@ -20,6 +20,7 @@ import org.junit.jupiter.api.Test;
import org.mockito.MockitoAnnotations;
import de.rwu.easydrop.api.dto.ProductDTO;
+import de.rwu.easydrop.exception.DataSourceException;
class AmazonProductDataSourceTest {
@@ -150,6 +151,7 @@ class AmazonProductDataSourceTest {
AmazonProductDataSource dataSource = mock(AmazonProductDataSource.class);
URL mockURL = mock(URL.class);
+ when(dataSource.getDataOrigin()).thenReturn(demoDataOrigin);
when(dataSource.createApiUrl(demoProductId)).thenReturn(mockURL);
when(dataSource.getProductDTOById(demoProductId)).thenCallRealMethod();
HttpURLConnection mockConnection = mock(HttpURLConnection.class);
@@ -157,7 +159,7 @@ class AmazonProductDataSourceTest {
when(mockConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_NOT_FOUND);
// Invoke the method and verify the exception
- IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> {
+ DataSourceException exception = assertThrows(DataSourceException.class, () -> {
dataSource.getProductDTOById(demoProductId);
});
@@ -170,6 +172,7 @@ class AmazonProductDataSourceTest {
// Set up the test environment
AmazonProductDataSource dataSource = mock(AmazonProductDataSource.class);
URL mockURL = mock(URL.class);
+ when(dataSource.getDataOrigin()).thenReturn(demoDataOrigin);
when(dataSource.createApiUrl(demoProductId)).thenReturn(mockURL);
when(dataSource.getProductDTOById(demoProductId)).thenCallRealMethod();
when(dataSource.buildProductDTO(any(), anyString())).thenCallRealMethod();
@@ -179,11 +182,23 @@ class AmazonProductDataSourceTest {
when(mockConnection.getInputStream()).thenThrow(new IOException());
// Invoke the method and verify the exception
- IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> {
+ DataSourceException exception = assertThrows(DataSourceException.class, () -> {
dataSource.getProductDTOById(demoProductId);
});
// Verify the exception message
assertEquals("Couldn't fulfill Amazon API request", exception.getMessage());
}
+
+ @Test
+ void getDataOrigin_ReturnsExpectedDataOrigin() {
+ String dataOrigin = demoDataSource.getDataOrigin();
+ assertEquals(demoDataOrigin, dataOrigin);
+ }
+
+ @Test
+ void getApiKey_ReturnsExpectedApiKey() {
+ String apiKey = demoDataSource.getApiKey();
+ assertEquals(demoApiKey, apiKey);
+ }
}
diff --git a/src/test/java/de/rwu/easydrop/api/client/DataSourceFactoryTest.java b/src/test/java/de/rwu/easydrop/api/client/DataSourceFactoryTest.java
new file mode 100644
index 0000000..c84df2a
--- /dev/null
+++ b/src/test/java/de/rwu/easydrop/api/client/DataSourceFactoryTest.java
@@ -0,0 +1,48 @@
+package de.rwu.easydrop.api.client;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.Mockito.when;
+
+import javax.naming.ConfigurationException;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import de.rwu.easydrop.util.Config;
+
+class DataSourceFactoryTest {
+ @Mock
+ private Config config;
+
+ private DataSourceFactory dataSourceFactory;
+
+ @BeforeEach
+ void setUp() throws ConfigurationException {
+ MockitoAnnotations.openMocks(this);
+ when(config.getProperty("AMAZON_API_URL")).thenReturn("https://api.amazon.com");
+ when(config.getProperty("AMAZON_API_KEY")).thenReturn("amazon-api-key");
+ when(config.getProperty("EBAY_API_URL")).thenReturn("https://api.ebay.com");
+ when(config.getProperty("EBAY_API_KEY")).thenReturn("ebay-api-key");
+ dataSourceFactory = new DataSourceFactory(config);
+ }
+
+ @Test
+ void createAmazonProductDataSource_ReturnsAmazonProductDataSource() {
+ // Act
+ AmazonProductDataSource dataSource = dataSourceFactory.createAmazonProductDataSource();
+
+ // Assert
+ assertEquals("amazon-api-key", dataSource.getApiKey());
+ }
+
+ @Test
+ void createEbayItemDataSource_ReturnsEbayItemDataSource() {
+ // Act
+ EbayItemDataSource dataSource = dataSourceFactory.createEbayItemDataSource();
+
+ // Assert
+ assertEquals("ebay-api-key", dataSource.getApiKey());
+ }
+}
diff --git a/src/test/java/de/rwu/easydrop/api/client/EbayItemDataSourceTest.java b/src/test/java/de/rwu/easydrop/api/client/EbayItemDataSourceTest.java
new file mode 100644
index 0000000..9a6ed45
--- /dev/null
+++ b/src/test/java/de/rwu/easydrop/api/client/EbayItemDataSourceTest.java
@@ -0,0 +1,125 @@
+package de.rwu.easydrop.api.client;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockitoAnnotations;
+
+import de.rwu.easydrop.api.dto.ProductDTO;
+import de.rwu.easydrop.exception.DataSourceException;
+
+class EbayItemDataSourceTest {
+ private EbayItemDataSource demoDataSource;
+
+ private static String demoApiKey = "my-api-key";
+ private static String demoApiUrl = "https://www.example.com/api";
+ private static String demoDataOrigin = "eBay";
+ private static String demoQuery = "iPhone";
+
+ @BeforeEach
+ void setUp() {
+ demoDataSource = new EbayItemDataSource(demoApiUrl, demoApiKey);
+ MockitoAnnotations.openMocks(this);
+ }
+
+ @Test
+ void testConstructor() {
+ // Assert
+ try {
+ Field baseUrlField = EbayItemDataSource.class.getDeclaredField("baseUrl");
+ baseUrlField.setAccessible(true);
+ Assertions.assertEquals(demoApiUrl, baseUrlField.get(demoDataSource));
+
+ Field apiKeyField = EbayItemDataSource.class.getDeclaredField("apiKey");
+ apiKeyField.setAccessible(true);
+ Assertions.assertEquals(demoApiKey, apiKeyField.get(demoDataSource));
+ } catch (NoSuchFieldException e) {
+ Assertions.fail();
+ } catch (IllegalAccessException e) {
+ Assertions.fail();
+ }
+ }
+
+ @Test
+ void createApiUrl_ValidSearchQuery_ReturnsValidUrl() throws MalformedURLException {
+ URL apiUrl = demoDataSource.createApiUrl(demoQuery);
+
+ assertNotNull(apiUrl);
+ assertEquals("https://www.example.com/api/buy/browse/v1/item_summary/search?q=iPhone&limit=1&offset=0",
+ apiUrl.toString());
+ }
+
+ @Test
+ void buildProductDTO_ValidJson_ReturnsValidProductDTO() {
+ ProductDTO product = new ProductDTO(demoQuery, demoDataOrigin);
+ String json = "{\"itemSummaries\":[{\"shippingOptions\":[{\"guaranteedDelivery\":true,\"shippingCost\":{\"value\":10}}],\"price\":{\"value\":999.99},\"seller\":{\"username\":\"seller123\"}}]}";
+
+ ProductDTO result = demoDataSource.buildProductDTO(product, json);
+
+ assertEquals(demoDataOrigin, result.getDataOrigin());
+ assertEquals(true, result.isAvailable());
+ assertEquals(999.99, result.getCurrentPrice());
+ assertEquals(10.0, result.getDeliveryPrice());
+ assertEquals("seller123", result.getMerchant());
+ }
+
+ @Test
+ void buildProductDTO_InvalidJson_ReturnsProductDTOWithDefaults() {
+ ProductDTO product = new ProductDTO(demoQuery, demoDataOrigin);
+ String json = "{\"itemSummaries\":[]}"; // Empty JSON to simulate missing data
+
+ ProductDTO result = demoDataSource.buildProductDTO(product, json);
+
+ assertEquals("eBay", result.getDataOrigin());
+ assertEquals(false, result.isAvailable()); // Default value for boolean
+ assertEquals(0.0, result.getCurrentPrice()); // Default value for double
+ assertEquals(0.0, result.getDeliveryPrice()); // Default value for double
+ assertEquals(null, result.getMerchant()); // Default value for String
+ }
+
+ @Test
+ void getDataOrigin_ReturnsExpectedDataOrigin() {
+ String dataOrigin = demoDataSource.getDataOrigin();
+ assertEquals(demoDataOrigin, dataOrigin);
+ }
+
+ @Test
+ void getApiKey_ReturnsExpectedApiKey() {
+ String apiKey = demoDataSource.getApiKey();
+ assertEquals(demoApiKey, apiKey);
+ }
+
+ @Test
+ void testGetProductDTOById_failedRequest() throws IOException {
+ // Set up the test environment
+
+ EbayItemDataSource dataSource = mock(EbayItemDataSource.class);
+ URL mockURL = mock(URL.class);
+ when(dataSource.getDataOrigin()).thenReturn(demoDataOrigin);
+ when(dataSource.createApiUrl(demoQuery)).thenReturn(mockURL);
+ when(dataSource.getProductDTOById(demoQuery)).thenCallRealMethod();
+ HttpURLConnection mockConnection = mock(HttpURLConnection.class);
+ when(mockURL.openConnection()).thenReturn(mockConnection);
+ when(mockConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_NOT_FOUND);
+
+ // Invoke the method and verify the exception
+ DataSourceException exception = assertThrows(DataSourceException.class, () -> {
+ dataSource.getProductDTOById(demoQuery);
+ });
+
+ // Verify the exception message
+ assertEquals("Nothing found: eBay API responded with error code 404", exception.getMessage());
+ }
+}
diff --git a/src/test/java/de/rwu/easydrop/api/dto/ProductDTOTest.java b/src/test/java/de/rwu/easydrop/api/dto/ProductDTOTest.java
index 9d5917a..1e16d7c 100644
--- a/src/test/java/de/rwu/easydrop/api/dto/ProductDTOTest.java
+++ b/src/test/java/de/rwu/easydrop/api/dto/ProductDTOTest.java
@@ -1,33 +1,56 @@
package de.rwu.easydrop.api.dto;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
import org.junit.jupiter.api.Test;
class ProductDTOTest {
+
@Test
- void testToString1() {
- ProductDTO product1 = new ProductDTO("12345", "Amazon");
- product1.setMerchant("Merchant A");
- product1.setCurrentPrice(19.99);
- product1.setAvailable(true);
+ void constructor_SetsProductIdAndDataOrigin() {
+ // Arrange
+ String productId = "12345";
+ String dataOrigin = "Amazon";
- String expectedString1 = "ProductDTO{12345 from Merchant A (Amazon) at 19,99 € (available: yes)}";
- String result1 = product1.toString();
+ // Act
+ ProductDTO productDTO = new ProductDTO(productId, dataOrigin);
- assertEquals(expectedString1, result1);
+ // Assert
+ assertEquals(productId, productDTO.getProductId());
+ assertEquals(dataOrigin, productDTO.getDataOrigin());
}
@Test
- void testToString2() {
- ProductDTO product2 = new ProductDTO("67890", "eBay");
- product2.setMerchant("Merchant B");
- product2.setCurrentPrice(9.99);
- product2.setAvailable(false);
+ void gettersAndSetters_WorkAsExpected() {
+ // Arrange
+ ProductDTO productDTO = new ProductDTO("12345", "Amazon");
- String expectedString2 = "ProductDTO{67890 from Merchant B (eBay) at 9,99 € (available: no)}";
- String result2 = product2.toString();
+ // Act and Assert
+ assertEquals("12345", productDTO.getProductId());
+ assertEquals("Amazon", productDTO.getDataOrigin());
- assertEquals(expectedString2, result2);
+ // Modify fields
+ productDTO.setProductId("54321");
+ productDTO.setDataOrigin("eBay");
+
+ // Assert
+ assertEquals("54321", productDTO.getProductId());
+ assertEquals("eBay", productDTO.getDataOrigin());
+ }
+
+ @Test
+ void defaultConstructor_SetsDefaultValues() {
+ // Act
+ ProductDTO productDTO = new ProductDTO(null, null);
+
+ // Assert
+ assertNull(productDTO.getProductId());
+ assertNull(productDTO.getDataOrigin());
+ assertEquals(0.0, productDTO.getCurrentPrice());
+ assertNull(productDTO.getMerchant());
+ assertEquals(0.0, productDTO.getDeliveryPrice());
+ assertFalse(productDTO.isAvailable());
}
}
diff --git a/src/test/java/de/rwu/easydrop/exception/DataSourceExceptionTest.java b/src/test/java/de/rwu/easydrop/exception/DataSourceExceptionTest.java
new file mode 100644
index 0000000..930e1bc
--- /dev/null
+++ b/src/test/java/de/rwu/easydrop/exception/DataSourceExceptionTest.java
@@ -0,0 +1,61 @@
+package de.rwu.easydrop.exception;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import org.junit.jupiter.api.Test;
+
+class DataSourceExceptionTest {
+
+ @Test
+ void constructor_WithMessage_SetsMessage() {
+ // Arrange
+ String message = "Data source error";
+
+ // Act
+ DataSourceException exception = new DataSourceException(message);
+
+ // Assert
+ assertEquals(message, exception.getMessage());
+ }
+
+ @Test
+ void constructor_WithMessageAndCause_SetsMessageAndCause() {
+ // Arrange
+ String message = "Data source error";
+ Throwable cause = new IllegalArgumentException("Invalid argument");
+
+ // Act
+ DataSourceException exception = new DataSourceException(message, cause);
+
+ // Assert
+ assertEquals(message, exception.getMessage());
+ assertEquals(cause, exception.getCause());
+ }
+
+ @Test
+ void constructor_WithNullMessage_SetsNullMessage() {
+ // Act
+ DataSourceException exception = new DataSourceException(null);
+
+ // Assert
+ assertEquals(null, exception.getMessage());
+ }
+
+ @Test
+ void constructor_WithNullCause_SetsNullCause() {
+ // Act
+ DataSourceException exception = new DataSourceException("Data source error", null);
+
+ // Assert
+ assertEquals(null, exception.getCause());
+ }
+
+ @Test
+ void throw_DataSourceException() {
+ // Act and Assert
+ assertThrows(DataSourceException.class, () -> {
+ throw new DataSourceException("Data source error");
+ });
+ }
+}
diff --git a/src/test/java/de/rwu/easydrop/exception/InvalidProductExceptionTest.java b/src/test/java/de/rwu/easydrop/exception/InvalidProductExceptionTest.java
new file mode 100644
index 0000000..478e8e3
--- /dev/null
+++ b/src/test/java/de/rwu/easydrop/exception/InvalidProductExceptionTest.java
@@ -0,0 +1,61 @@
+package de.rwu.easydrop.exception;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import org.junit.jupiter.api.Test;
+
+class InvalidProductExceptionTest {
+
+ @Test
+ void constructor_WithMessage_SetsMessage() {
+ // Arrange
+ String message = "Invalid product data";
+
+ // Act
+ InvalidProductException exception = new InvalidProductException(message);
+
+ // Assert
+ assertEquals(message, exception.getMessage());
+ }
+
+ @Test
+ void constructor_WithMessageAndCause_SetsMessageAndCause() {
+ // Arrange
+ String message = "Invalid product data";
+ Throwable cause = new IllegalArgumentException("Invalid argument");
+
+ // Act
+ InvalidProductException exception = new InvalidProductException(message, cause);
+
+ // Assert
+ assertEquals(message, exception.getMessage());
+ assertEquals(cause, exception.getCause());
+ }
+
+ @Test
+ void constructor_WithNullMessage_SetsNullMessage() {
+ // Act
+ InvalidProductException exception = new InvalidProductException(null);
+
+ // Assert
+ assertEquals(null, exception.getMessage());
+ }
+
+ @Test
+ void constructor_WithNullCause_SetsNullCause() {
+ // Act
+ InvalidProductException exception = new InvalidProductException("Invalid product data", null);
+
+ // Assert
+ assertEquals(null, exception.getCause());
+ }
+
+ @Test
+ void throw_InvalidProductException() {
+ // Act and Assert
+ assertThrows(InvalidProductException.class, () -> {
+ throw new InvalidProductException("Invalid product data");
+ });
+ }
+}
diff --git a/src/test/java/de/rwu/easydrop/model/ProductTest.java b/src/test/java/de/rwu/easydrop/model/ProductTest.java
new file mode 100644
index 0000000..1845b65
--- /dev/null
+++ b/src/test/java/de/rwu/easydrop/model/ProductTest.java
@@ -0,0 +1,75 @@
+package de.rwu.easydrop.model;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+
+class ProductTest {
+ @Test
+ void testToString1() {
+ Product product1 = new Product();
+ product1.setDataOrigin("Amazon");
+ product1.setProductId("12345");
+ product1.setMerchant("Merchant A");
+ product1.setCurrentPrice(19.99);
+ product1.setAvailable(true);
+
+ String expectedString1 = "Product: [12345 from Merchant A (Amazon) at 19,99 € (available: yes)]";
+ String result1 = product1.toString();
+
+ assertEquals(expectedString1, result1);
+ }
+
+ @Test
+ void testToString2() {
+ Product product2 = new Product();
+ product2.setDataOrigin("eBay");
+ product2.setProductId("67890");
+ product2.setMerchant("Merchant B");
+ product2.setCurrentPrice(9.99);
+ product2.setAvailable(false);
+
+ String expectedString2 = "Product: [67890 from Merchant B (eBay) at 9,99 € (available: no)]";
+ String result2 = product2.toString();
+
+ assertEquals(expectedString2, result2);
+ }
+
+ @Test
+ void gettersAndSetters_WorkAsExpected() {
+ // Arrange
+ Product product = new Product();
+ product.setDataOrigin("Amazon");
+ product.setProductId("12345");
+ product.setCurrentPrice(9.99);
+ product.setMerchant("Example Merchant");
+ product.setDeliveryPrice(2.50);
+ product.setAvailable(true);
+
+ // Act and Assert
+ assertEquals("Amazon", product.getDataOrigin());
+ assertEquals("12345", product.getProductId());
+ assertEquals(9.99, product.getCurrentPrice());
+ assertEquals("Example Merchant", product.getMerchant());
+ assertEquals(2.50, product.getDeliveryPrice());
+ assertTrue(product.isAvailable());
+
+ // Modify fields
+ product.setDataOrigin("eBay");
+ product.setProductId("54321");
+ product.setCurrentPrice(19.99);
+ product.setMerchant("New Merchant");
+ product.setDeliveryPrice(3.50);
+ product.setAvailable(false);
+
+ // Assert
+ assertEquals("eBay", product.getDataOrigin());
+ assertEquals("54321", product.getProductId());
+ assertEquals(19.99, product.getCurrentPrice());
+ assertEquals("New Merchant", product.getMerchant());
+ assertEquals(3.50, product.getDeliveryPrice());
+ assertFalse(product.isAvailable());
+ }
+}
diff --git a/src/test/java/de/rwu/easydrop/service/mapping/ProductMapperTest.java b/src/test/java/de/rwu/easydrop/service/mapping/ProductMapperTest.java
new file mode 100644
index 0000000..6dbf741
--- /dev/null
+++ b/src/test/java/de/rwu/easydrop/service/mapping/ProductMapperTest.java
@@ -0,0 +1,56 @@
+package de.rwu.easydrop.service.mapping;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Modifier;
+
+import org.junit.jupiter.api.Test;
+
+import de.rwu.easydrop.api.dto.ProductDTO;
+import de.rwu.easydrop.model.Product;
+
+class ProductMapperTest {
+ @Test
+ void testConstructorIsPrivate()
+ throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
+ // Check for private constructor
+ Constructor constructor = ProductMapper.class.getDeclaredConstructor();
+ assertTrue(Modifier.isPrivate(constructor.getModifiers()));
+
+ // Make sure exception is thrown when instantiating
+ constructor.setAccessible(true);
+ assertThrows(InvocationTargetException.class, () -> {
+ constructor.newInstance();
+ });
+ }
+
+ @Test
+ void mapProductFromDTO_ReturnsProductWithMappedFields() {
+ // Arrange
+ ProductDTO dto = createProductDTO();
+
+ // Act
+ Product product = ProductMapper.mapProductFromDTO(dto);
+
+ // Assert
+ assertEquals(dto.isAvailable(), product.isAvailable());
+ assertEquals(dto.getCurrentPrice(), product.getCurrentPrice());
+ assertEquals(dto.getDataOrigin(), product.getDataOrigin());
+ assertEquals(dto.getDeliveryPrice(), product.getDeliveryPrice());
+ assertEquals(dto.getMerchant(), product.getMerchant());
+ assertEquals(dto.getProductId(), product.getProductId());
+ }
+
+ private ProductDTO createProductDTO() {
+ ProductDTO dto = new ProductDTO("12345", "Amazon");
+ dto.setAvailable(true);
+ dto.setCurrentPrice(9.99);
+ dto.setDeliveryPrice(2.50);
+ dto.setMerchant("Example Merchant");
+ return dto;
+ }
+}
diff --git a/src/test/java/de/rwu/easydrop/service/retriever/ProductRetrieverTest.java b/src/test/java/de/rwu/easydrop/service/retriever/ProductRetrieverTest.java
new file mode 100644
index 0000000..36dff9b
--- /dev/null
+++ b/src/test/java/de/rwu/easydrop/service/retriever/ProductRetrieverTest.java
@@ -0,0 +1,87 @@
+package de.rwu.easydrop.service.retriever;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import javax.naming.ConfigurationException;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import de.rwu.easydrop.api.client.AmazonProductDataSource;
+import de.rwu.easydrop.api.client.DataSourceFactory;
+import de.rwu.easydrop.api.client.EbayItemDataSource;
+import de.rwu.easydrop.api.dto.ProductDTO;
+import de.rwu.easydrop.model.Product;
+import de.rwu.easydrop.util.Config;
+
+class ProductRetrieverTest {
+ @Mock
+ private Config config;
+ @Mock
+ private DataSourceFactory dataSourceFactory;
+ @Mock
+ private AmazonProductDataSource amazonDataSource;
+ @Mock
+ private EbayItemDataSource ebayDataSource;
+ @Mock
+ private ProductDTO productDTO;
+ @Mock
+ private Product product;
+
+ private ProductRetriever productRetriever;
+
+ @BeforeEach
+ void setUp() throws ConfigurationException {
+ MockitoAnnotations.openMocks(this);
+ when(config.getProperty("AMAZON_API_URL")).thenReturn("https://api.amazon.com");
+ when(config.getProperty("AMAZON_API_KEY")).thenReturn("amazon-api-key");
+ dataSourceFactory.setConfig(config);
+ productRetriever = new ProductRetriever(dataSourceFactory);
+ }
+
+ @Test
+ void getProductFromAmazon_ReturnsProduct() {
+ // Arrange
+ String asin = "B01234ABC";
+ when(dataSourceFactory.createAmazonProductDataSource()).thenReturn(amazonDataSource);
+ when(amazonDataSource.getProductDTOById(asin)).thenReturn(productDTO);
+ when(productDTO.getProductId()).thenReturn(asin);
+ when(productDTO.getCurrentPrice()).thenReturn(9.99);
+ when(productDTO.getDataOrigin()).thenReturn("Amazon");
+
+ // Act
+ Product result = productRetriever.getProductFromAmazon(asin);
+
+ // Assert
+ assertNotNull(result);
+ assertEquals(asin, result.getProductId());
+ assertEquals(9.99, result.getCurrentPrice());
+ verify(amazonDataSource, times(1)).getProductDTOById(asin);
+ }
+
+ @Test
+ void getProductFromEbay_ReturnsProduct() {
+ // Arrange
+ String productQuery = "MySearchQuery";
+ when(dataSourceFactory.createEbayItemDataSource()).thenReturn(ebayDataSource);
+ when(ebayDataSource.getProductDTOById(productQuery)).thenReturn(productDTO);
+ when(productDTO.getProductId()).thenReturn(productQuery);
+ when(productDTO.getCurrentPrice()).thenReturn(9.99);
+ when(productDTO.getDataOrigin()).thenReturn("eBay");
+
+ // Act
+ Product result = productRetriever.getProductFromEbay(productQuery);
+
+ // Assert
+ assertNotNull(result);
+ assertEquals(productQuery, result.getProductId());
+ assertEquals(9.99, result.getCurrentPrice());
+ verify(ebayDataSource, times(1)).getProductDTOById(productQuery);
+ }
+}
diff --git a/src/test/java/de/rwu/easydrop/service/validation/ProductValidatorTest.java b/src/test/java/de/rwu/easydrop/service/validation/ProductValidatorTest.java
new file mode 100644
index 0000000..7827bbb
--- /dev/null
+++ b/src/test/java/de/rwu/easydrop/service/validation/ProductValidatorTest.java
@@ -0,0 +1,109 @@
+package de.rwu.easydrop.service.validation;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Modifier;
+import java.util.stream.Stream;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import de.rwu.easydrop.exception.InvalidProductException;
+import de.rwu.easydrop.model.Product;
+
+class ProductValidatorTest {
+
+ @Test
+ void testConstructorIsPrivate()
+ throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
+ // Check for private constructor
+ Constructor constructor = ProductValidator.class.getDeclaredConstructor();
+ assertTrue(Modifier.isPrivate(constructor.getModifiers()));
+
+ // Make sure exception is thrown when instantiating
+ constructor.setAccessible(true);
+ assertThrows(InvocationTargetException.class, () -> {
+ constructor.newInstance();
+ });
+ }
+
+ @Test
+ void validate_ValidProduct_NoExceptionThrown() {
+ // Arrange
+ Product product = new Product();
+ product.setCurrentPrice(9.99);
+ product.setDataOrigin("Amazon");
+ product.setProductId("12345");
+
+ // Act and Assert
+ assertDoesNotThrow(() -> ProductValidator.validate(product));
+ }
+
+ @Test
+ void isInValidDataOrigins_ValidDataOrigin_ReturnsTrue() {
+ // Arrange
+ String dataOrigin = "Amazon";
+
+ // Act
+ boolean result = ProductValidator.isInValidDataOrigins(dataOrigin);
+
+ // Assert
+ assertTrue(result);
+ }
+
+ @Test
+ void isInValidDataOrigins_InvalidDataOrigin_ReturnsFalse() {
+ // Arrange
+ String dataOrigin = "UnknownOrigin";
+
+ // Act
+ boolean result = ProductValidator.isInValidDataOrigins(dataOrigin);
+
+ // Assert
+ assertFalse(result);
+ }
+
+ @ParameterizedTest
+ @MethodSource("invalidProductProvider")
+ void validate_InvalidProduct_ThrowsInvalidProductException(Product product) {
+ // Act and Assert
+ assertThrows(InvalidProductException.class, () -> ProductValidator.validate(product));
+ }
+
+ static Stream invalidProductProvider() {
+ return Stream.of(
+ createProductWithZeroPrice(),
+ createProductWithUnknownDataOrigin(),
+ createProductWithEmptyProductId());
+ }
+
+ private static Product createProductWithZeroPrice() {
+ Product product = new Product();
+ product.setCurrentPrice(0.00);
+ product.setDataOrigin("Amazon");
+ product.setProductId("12345");
+ return product;
+ }
+
+ private static Product createProductWithUnknownDataOrigin() {
+ Product product = new Product();
+ product.setCurrentPrice(9.99);
+ product.setDataOrigin("UnknownOrigin");
+ product.setProductId("12345");
+ return product;
+ }
+
+ private static Product createProductWithEmptyProductId() {
+ Product product = new Product();
+ product.setCurrentPrice(9.99);
+ product.setDataOrigin("Amazon");
+ product.setProductId("");
+ return product;
+ }
+}
diff --git a/src/test/java/de/rwu/easydrop/util/ConfigImplTest.java b/src/test/java/de/rwu/easydrop/util/ConfigImplTest.java
index db7de79..59cece7 100644
--- a/src/test/java/de/rwu/easydrop/util/ConfigImplTest.java
+++ b/src/test/java/de/rwu/easydrop/util/ConfigImplTest.java
@@ -1,6 +1,7 @@
package de.rwu.easydrop.util;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.fail;
@@ -13,7 +14,7 @@ import org.junit.jupiter.api.Test;
class ConfigImplTest {
private Config config;
- private final static String TESTDATA_PATH = "testResources/testdata.properties";
+ private final static String TESTDATA_PATH = "src/test/resources/testdata.properties";
private final static String TESTDATA_KEY = "API_KEY";
private final static String TESTDATA_VAL = "keyIsHere";
@@ -34,7 +35,9 @@ class ConfigImplTest {
}
@Test
- void testGetProperty_ConfigNotLoaded() {
+ void testGetProperty_ConfigNotLoaded() throws Exception {
+ config.reset();
+
NoSuchElementException exception = assertThrows(NoSuchElementException.class, () -> {
config.getProperty(TESTDATA_KEY);
});
@@ -74,7 +77,7 @@ class ConfigImplTest {
@Test
void testLoadConfigSuccessfully() {
try {
- config.setConfigLocation("testResources/testdata.properties");
+ config.setConfigLocation("src/test/resources/testdata.properties");
config.loadConfig();
assertEquals(TESTDATA_VAL, config.getProperty(TESTDATA_KEY));
} catch (ConfigurationException e) {
@@ -92,4 +95,19 @@ class ConfigImplTest {
assertEquals("Couldn't load required config file", exception.getMessage());
}
+
+ @Test
+ void testReset() throws ConfigurationException {
+ config.setConfigLocation("src/test/resources/testdata.properties");
+ config.loadConfig();
+
+ assertNotNull(config.getProperty(TESTDATA_KEY));
+ config.reset();
+
+ NoSuchElementException exception = assertThrows(NoSuchElementException.class, () -> {
+ config.getProperty(TESTDATA_KEY);
+ });
+
+ assertEquals("Config has not been loaded", exception.getMessage());
+ }
}
diff --git a/src/test/java/de/rwu/easydrop/util/ConfigTest.java b/src/test/java/de/rwu/easydrop/util/ConfigTest.java
index 8cf0c2a..2b08b0a 100644
--- a/src/test/java/de/rwu/easydrop/util/ConfigTest.java
+++ b/src/test/java/de/rwu/easydrop/util/ConfigTest.java
@@ -2,6 +2,7 @@ package de.rwu.easydrop.util;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
import static org.mockito.Mockito.spy;
import javax.naming.ConfigurationException;
@@ -20,17 +21,18 @@ class ConfigTest {
}
@Test
- void testGetInstanceNull() {
- config = null;
-
+ void testGetInstance() {
Config newConfig = Config.getInstance();
assertNotNull(newConfig);
}
@Test
- void testGetInstanceNotNull() {
- Config newConfig = Config.getInstance();
- assertNotNull(newConfig);
+ void testGetInstanceEquality() {
+ // Create "two" instances to check validity of Singleton pattern
+ Config instance1 = Config.getInstance();
+ Config instance2 = Config.getInstance();
+
+ assertSame(instance1, instance2, "Instances should be equal");
}
@Test
diff --git a/src/test/resources/empty.properties b/src/test/resources/empty.properties
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/src/test/resources/empty.properties
@@ -0,0 +1 @@
+
diff --git a/src/test/resources/testdata.properties b/src/test/resources/testdata.properties
new file mode 100644
index 0000000..71176b3
--- /dev/null
+++ b/src/test/resources/testdata.properties
@@ -0,0 +1,5 @@
+API_KEY=keyIsHere
+AMAZON_API_URL=THE_AMAZON_API_URL
+AMAZON_API_KEY=THE_AMAZON_API_KEY
+EBAY_API_URL=THE_EBAY_API_URL
+EBAY_API_KEY=THE_EBAY_API_KEY
diff --git a/testResources/empty.properties b/testResources/empty.properties
deleted file mode 100644
index e69de29..0000000
diff --git a/testResources/testdata.properties b/testResources/testdata.properties
deleted file mode 100644
index cbf5875..0000000
--- a/testResources/testdata.properties
+++ /dev/null
@@ -1 +0,0 @@
-API_KEY=keyIsHere
\ No newline at end of file