Merge branch '#37-eBay-Product-API' into 'dev'
eBay Product API See merge request team1/sandbox2!3
This commit is contained in:
9
.vscode/settings.json
vendored
9
.vscode/settings.json
vendored
@@ -1,3 +1,8 @@
|
|||||||
{
|
{
|
||||||
"java.configuration.updateBuildConfiguration": "automatic"
|
"java.configuration.updateBuildConfiguration": "automatic",
|
||||||
}
|
"sonarlint.connectedMode.project": {
|
||||||
|
"connectionId": "LocalSonarQube",
|
||||||
|
"projectKey": "EasyDrop"
|
||||||
|
},
|
||||||
|
"java.debug.settings.onBuildFailureProceed": true
|
||||||
|
}
|
||||||
|
|||||||
28
CHANGELOG.md
28
CHANGELOG.md
@@ -1,10 +1,34 @@
|
|||||||
# Changelog
|
# 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
|
## 0.1.0
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- (DataSource) → AmazonProductDataSource as first external data source (#39)
|
- (DataSource) → `AmazonProductDataSource` as first external data source (#39)
|
||||||
- ProductDTO as data holder structure for data from external sources (~ #39)
|
- `ProductDTO` as data holder structure for data from external sources (~ #39)
|
||||||
- Config for credential, base URLs etc. (~ #39)
|
- Config for credential, base URLs etc. (~ #39)
|
||||||
- FormattingUtil for formatting price strings (~ #39)
|
- FormattingUtil for formatting price strings (~ #39)
|
||||||
|
|||||||
133
SampleResponses/eBayProductAPISample.json
Normal file
133
SampleResponses/eBayProductAPISample.json
Normal file
@@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
5
Script/SonarQube_Local.sh
Normal file
5
Script/SonarQube_Local.sh
Normal file
@@ -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
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
# Amazon Credentials
|
# Amazon Credentials
|
||||||
AMAZON_API_URL=
|
AMAZON_API_URL=
|
||||||
AMAZON_API_KEY=
|
AMAZON_API_KEY=
|
||||||
|
EBAY_API_URL=
|
||||||
|
EBAY_API_KEY=
|
||||||
2
lombok.config
Normal file
2
lombok.config
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
config.stopBubbling = true
|
||||||
|
lombok.addLombokGeneratedAnnotation = true
|
||||||
19
pom.xml
19
pom.xml
@@ -5,7 +5,7 @@
|
|||||||
<groupId>de.rwu</groupId>
|
<groupId>de.rwu</groupId>
|
||||||
<artifactId>easydrop</artifactId>
|
<artifactId>easydrop</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<version>0.1.0</version>
|
<version>0.2.0-SNAPSHOT</version>
|
||||||
<name>EasyDrop</name>
|
<name>EasyDrop</name>
|
||||||
<url>http://maven.apache.org</url>
|
<url>http://maven.apache.org</url>
|
||||||
|
|
||||||
@@ -16,16 +16,29 @@
|
|||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>1.18.28</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.junit.jupiter</groupId>
|
<groupId>org.junit.jupiter</groupId>
|
||||||
<artifactId>junit-jupiter-api</artifactId>
|
<artifactId>junit-jupiter-api</artifactId>
|
||||||
<version>5.8.0</version>
|
<version>5.9.3</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.junit.jupiter</groupId>
|
<groupId>org.junit.jupiter</groupId>
|
||||||
<artifactId>junit-jupiter-engine</artifactId>
|
<artifactId>junit-jupiter-engine</artifactId>
|
||||||
<version>5.8.0</version>
|
<version>5.9.3</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-params</artifactId>
|
||||||
|
<version>5.9.3</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ import javax.naming.ConfigurationException;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
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;
|
import de.rwu.easydrop.util.Config;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -33,17 +34,12 @@ public final class Main {
|
|||||||
*/
|
*/
|
||||||
public static void main(final String[] args) throws ConfigurationException {
|
public static void main(final String[] args) throws ConfigurationException {
|
||||||
Config config = Config.getInstance();
|
Config config = Config.getInstance();
|
||||||
config.loadConfig();
|
DataSourceFactory dataSourceFactory = new DataSourceFactory(config);
|
||||||
String amznBaseUrl = config.getProperty("AMAZON_API_URL");
|
ProductRetriever retriever = new ProductRetriever(dataSourceFactory);
|
||||||
String amznApiKey = config.getProperty("AMAZON_API_KEY");
|
|
||||||
String testProduct = null;
|
|
||||||
|
|
||||||
AmazonProductDataSource amznSrc = new AmazonProductDataSource(amznBaseUrl, amznApiKey);
|
String amznProduct = retriever.getProductFromAmazon("B096Y2TYKV").toString();
|
||||||
try {
|
LOGGER.info(amznProduct);
|
||||||
testProduct = amznSrc.getProductDTOById("B096Y2TYKV").toString();
|
String ebayProduct = retriever.getProductFromEbay("Gigabyte GeForce RTX 3060").toString();
|
||||||
LOGGER.info(testProduct);
|
LOGGER.info(ebayProduct);
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
LOGGER.error("Something went wrong :(", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
100
src/main/java/de/rwu/easydrop/api/client/AbstractDataSource.java
Normal file
100
src/main/java/de/rwu/easydrop/api/client/AbstractDataSource.java
Normal file
@@ -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;
|
||||||
|
}
|
||||||
@@ -1,9 +1,5 @@
|
|||||||
package de.rwu.easydrop.api.client;
|
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.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
|
||||||
@@ -18,7 +14,7 @@ import de.rwu.easydrop.api.dto.ProductDTO;
|
|||||||
*
|
*
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
public final class AmazonProductDataSource implements DataSource {
|
public final class AmazonProductDataSource extends AbstractDataSource {
|
||||||
/**
|
/**
|
||||||
* Name of this data source.
|
* Name of this data source.
|
||||||
*/
|
*/
|
||||||
@@ -28,7 +24,7 @@ public final class AmazonProductDataSource implements DataSource {
|
|||||||
*/
|
*/
|
||||||
private String baseUrl;
|
private String baseUrl;
|
||||||
/**
|
/**
|
||||||
* Credential key to authorize acccess.
|
* Credential key to authorize access.
|
||||||
*/
|
*/
|
||||||
private String apiKey;
|
private String apiKey;
|
||||||
/**
|
/**
|
||||||
@@ -52,48 +48,7 @@ public final class AmazonProductDataSource implements DataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ProductDTO getProductDTOById(final String productId) throws IllegalArgumentException {
|
protected ProductDTO buildProductDTO(final ProductDTO product, final String json) {
|
||||||
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) {
|
|
||||||
String root = "$.featuredOffer.";
|
String root = "$.featuredOffer.";
|
||||||
ReadContext ctx = JsonPath.parse(json);
|
ReadContext ctx = JsonPath.parse(json);
|
||||||
|
|
||||||
@@ -112,8 +67,11 @@ public final class AmazonProductDataSource implements DataSource {
|
|||||||
return product;
|
return product;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param productId ASIN
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public URL createApiUrl(final String productId) throws MalformedURLException {
|
protected URL createApiUrl(final String productId) throws MalformedURLException {
|
||||||
return new URL(baseUrl
|
return new URL(baseUrl
|
||||||
+ "/products/2020-08-26/products/"
|
+ "/products/2020-08-26/products/"
|
||||||
+ productId
|
+ productId
|
||||||
@@ -122,4 +80,14 @@ public final class AmazonProductDataSource implements DataSource {
|
|||||||
+ "&locale="
|
+ "&locale="
|
||||||
+ LOCALE);
|
+ LOCALE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getDataOrigin() {
|
||||||
|
return DATA_ORIGIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getApiKey() {
|
||||||
|
return this.apiKey;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
package de.rwu.easydrop.api.client;
|
package de.rwu.easydrop.api.client;
|
||||||
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URL;
|
|
||||||
|
|
||||||
import de.rwu.easydrop.api.dto.ProductDTO;
|
import de.rwu.easydrop.api.dto.ProductDTO;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -12,17 +9,8 @@ public interface DataSource {
|
|||||||
/**
|
/**
|
||||||
* Retrieves product info from the data source.
|
* Retrieves product info from the data source.
|
||||||
*
|
*
|
||||||
* @param productId ASIN
|
* @param productIdentifier Product identifier
|
||||||
* @return ProductDTO
|
* @return ProductDTO
|
||||||
*/
|
*/
|
||||||
ProductDTO getProductDTOById(String productId);
|
ProductDTO getProductDTOById(String productIdentifier);
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an URL object to connect to the API with.
|
|
||||||
*
|
|
||||||
* @param productId ASIN
|
|
||||||
* @return URL object
|
|
||||||
* @throws MalformedURLException
|
|
||||||
*/
|
|
||||||
URL createApiUrl(String productId) throws MalformedURLException;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,139 +1,52 @@
|
|||||||
package de.rwu.easydrop.api.dto;
|
package de.rwu.easydrop.api.dto;
|
||||||
|
|
||||||
import de.rwu.easydrop.util.FormattingUtil;
|
import lombok.Data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Product data transfer object.
|
* Product data transfer object.
|
||||||
*
|
*
|
||||||
* @since 0.1.0
|
* @since 0.1.0
|
||||||
*/
|
*/
|
||||||
|
@Data
|
||||||
public class ProductDTO {
|
public class ProductDTO {
|
||||||
/**
|
/**
|
||||||
* Data source platform, like "Amazon".
|
* Data source platform, like "Amazon".
|
||||||
*/
|
*/
|
||||||
private String dataOrigin;
|
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.
|
* Platform internal product identifier.
|
||||||
*/
|
*/
|
||||||
private String productId;
|
private String productId;
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the productId
|
|
||||||
*/
|
|
||||||
public String getProductId() {
|
|
||||||
return productId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Current product price per piece in Euro.
|
* Current product price per piece in Euro.
|
||||||
*/
|
*/
|
||||||
private double currentPrice;
|
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.
|
* Name of mercant offering the product on the platform.
|
||||||
*/
|
*/
|
||||||
private String merchant;
|
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.
|
* Additional Cost for delivery in Euro.
|
||||||
*/
|
*/
|
||||||
private double deliveryPrice;
|
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.
|
* Whether the product can be purchased at this point.
|
||||||
*/
|
*/
|
||||||
private boolean available;
|
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.
|
* Creates ProductDTO instance.
|
||||||
*
|
*
|
||||||
* @param newProductId Interal Product indetifier
|
* @param newProductId Internal Product indetifier
|
||||||
* @param newDataOrigin Data Origin
|
* @param newDataOrigin Data Origin
|
||||||
*/
|
*/
|
||||||
public ProductDTO(final String newProductId, final String newDataOrigin) {
|
public ProductDTO(final String newProductId, final String newDataOrigin) {
|
||||||
this.productId = newProductId;
|
this.productId = newProductId;
|
||||||
this.dataOrigin = newDataOrigin;
|
this.dataOrigin = newDataOrigin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public final String toString() {
|
|
||||||
return "ProductDTO{"
|
|
||||||
+ productId + " from "
|
|
||||||
+ merchant + " ("
|
|
||||||
+ dataOrigin + ")"
|
|
||||||
+ " at "
|
|
||||||
+ FormattingUtil.formatEuro(currentPrice) + " (available: "
|
|
||||||
+ (available ? "yes" : "no") + ")}";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
package de.rwu.easydrop.data.model;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A Product.
|
|
||||||
*
|
|
||||||
* TODO implement
|
|
||||||
*/
|
|
||||||
public class Product {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
/**
|
|
||||||
* Business objects.
|
|
||||||
*
|
|
||||||
* TODO implement
|
|
||||||
*/
|
|
||||||
package de.rwu.easydrop.data.model;
|
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
/**
|
||||||
|
* Contains EasyDrop-related custom exceptions.
|
||||||
|
*
|
||||||
|
* @since 0.2.0
|
||||||
|
*/
|
||||||
|
package de.rwu.easydrop.exception;
|
||||||
53
src/main/java/de/rwu/easydrop/model/Product.java
Normal file
53
src/main/java/de/rwu/easydrop/model/Product.java
Normal file
@@ -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") + ")]";
|
||||||
|
}
|
||||||
|
}
|
||||||
6
src/main/java/de/rwu/easydrop/model/package-info.java
Normal file
6
src/main/java/de/rwu/easydrop/model/package-info.java
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
/**
|
||||||
|
* Business objects.
|
||||||
|
*
|
||||||
|
* @since 0.2.0
|
||||||
|
*/
|
||||||
|
package de.rwu.easydrop.model;
|
||||||
@@ -1,14 +1,44 @@
|
|||||||
package de.rwu.easydrop.service.mapping;
|
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.
|
* Maps between Product, ProductDAO and ProductDTO.
|
||||||
*
|
*
|
||||||
* TODO implement
|
* @since 0.2.0
|
||||||
*
|
*
|
||||||
* @see Product
|
* @see Product
|
||||||
* @see ProductDTO
|
* @see ProductDTO
|
||||||
* @see ProductDAO
|
* @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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Maps different formats of corresponding objects.
|
* Maps different formats of corresponding objects.
|
||||||
*
|
*
|
||||||
* TODO implement
|
* @since 0.2.0
|
||||||
*/
|
*/
|
||||||
package de.rwu.easydrop.service.mapping;
|
package de.rwu.easydrop.service.mapping;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
/**
|
||||||
|
* Retrieves Objects from a data source.
|
||||||
|
*
|
||||||
|
* @since 0.2.0
|
||||||
|
*/
|
||||||
|
package de.rwu.easydrop.service.retriever;
|
||||||
@@ -1,10 +1,56 @@
|
|||||||
package de.rwu.easydrop.service.validation;
|
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.
|
* 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<String> validOrigins = new HashSet<>();
|
||||||
|
|
||||||
|
validOrigins.add("Amazon");
|
||||||
|
validOrigins.add("eBay");
|
||||||
|
|
||||||
|
return validOrigins.contains(dataOrigin);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Supports validation processes.
|
* Supports validation processes.
|
||||||
*
|
*
|
||||||
* TODO implement
|
* @since 0.2.0
|
||||||
*/
|
*/
|
||||||
package de.rwu.easydrop.service.validation;
|
package de.rwu.easydrop.service.validation;
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ public final class Config {
|
|||||||
*/
|
*/
|
||||||
public static Config getInstance() {
|
public static Config getInstance() {
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
return new Config();
|
instance = new Config();
|
||||||
}
|
}
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
@@ -109,4 +109,11 @@ public final class Config {
|
|||||||
public void setProperty(final String key, final String value) {
|
public void setProperty(final String key, final String value) {
|
||||||
properties.setProperty(key, value);
|
properties.setProperty(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the config's properties.
|
||||||
|
*/
|
||||||
|
public void reset() {
|
||||||
|
properties = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,4 +27,14 @@ public final class FormattingUtil {
|
|||||||
public static String formatEuro(final double amount) {
|
public static String formatEuro(final double amount) {
|
||||||
return String.format(Locale.GERMAN, "%,.2f", 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(" ", "+");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
<configuration>
|
<configuration>
|
||||||
|
<logger name="com.jayway.jsonpath" level="OFF" />
|
||||||
|
|
||||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
<encoder>
|
<encoder>
|
||||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||||
@@ -6,7 +8,7 @@
|
|||||||
</encoder>
|
</encoder>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
<root level="info">
|
<root level="INFO">
|
||||||
<appender-ref ref="STDOUT" />
|
<appender-ref ref="STDOUT" />
|
||||||
</root>
|
</root>
|
||||||
</configuration>
|
</configuration>
|
||||||
@@ -20,6 +20,7 @@ import org.junit.jupiter.api.Test;
|
|||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
import de.rwu.easydrop.api.dto.ProductDTO;
|
import de.rwu.easydrop.api.dto.ProductDTO;
|
||||||
|
import de.rwu.easydrop.exception.DataSourceException;
|
||||||
|
|
||||||
class AmazonProductDataSourceTest {
|
class AmazonProductDataSourceTest {
|
||||||
|
|
||||||
@@ -150,6 +151,7 @@ class AmazonProductDataSourceTest {
|
|||||||
|
|
||||||
AmazonProductDataSource dataSource = mock(AmazonProductDataSource.class);
|
AmazonProductDataSource dataSource = mock(AmazonProductDataSource.class);
|
||||||
URL mockURL = mock(URL.class);
|
URL mockURL = mock(URL.class);
|
||||||
|
when(dataSource.getDataOrigin()).thenReturn(demoDataOrigin);
|
||||||
when(dataSource.createApiUrl(demoProductId)).thenReturn(mockURL);
|
when(dataSource.createApiUrl(demoProductId)).thenReturn(mockURL);
|
||||||
when(dataSource.getProductDTOById(demoProductId)).thenCallRealMethod();
|
when(dataSource.getProductDTOById(demoProductId)).thenCallRealMethod();
|
||||||
HttpURLConnection mockConnection = mock(HttpURLConnection.class);
|
HttpURLConnection mockConnection = mock(HttpURLConnection.class);
|
||||||
@@ -157,7 +159,7 @@ class AmazonProductDataSourceTest {
|
|||||||
when(mockConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_NOT_FOUND);
|
when(mockConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_NOT_FOUND);
|
||||||
|
|
||||||
// Invoke the method and verify the exception
|
// Invoke the method and verify the exception
|
||||||
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> {
|
DataSourceException exception = assertThrows(DataSourceException.class, () -> {
|
||||||
dataSource.getProductDTOById(demoProductId);
|
dataSource.getProductDTOById(demoProductId);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -170,6 +172,7 @@ class AmazonProductDataSourceTest {
|
|||||||
// Set up the test environment
|
// Set up the test environment
|
||||||
AmazonProductDataSource dataSource = mock(AmazonProductDataSource.class);
|
AmazonProductDataSource dataSource = mock(AmazonProductDataSource.class);
|
||||||
URL mockURL = mock(URL.class);
|
URL mockURL = mock(URL.class);
|
||||||
|
when(dataSource.getDataOrigin()).thenReturn(demoDataOrigin);
|
||||||
when(dataSource.createApiUrl(demoProductId)).thenReturn(mockURL);
|
when(dataSource.createApiUrl(demoProductId)).thenReturn(mockURL);
|
||||||
when(dataSource.getProductDTOById(demoProductId)).thenCallRealMethod();
|
when(dataSource.getProductDTOById(demoProductId)).thenCallRealMethod();
|
||||||
when(dataSource.buildProductDTO(any(), anyString())).thenCallRealMethod();
|
when(dataSource.buildProductDTO(any(), anyString())).thenCallRealMethod();
|
||||||
@@ -179,11 +182,23 @@ class AmazonProductDataSourceTest {
|
|||||||
when(mockConnection.getInputStream()).thenThrow(new IOException());
|
when(mockConnection.getInputStream()).thenThrow(new IOException());
|
||||||
|
|
||||||
// Invoke the method and verify the exception
|
// Invoke the method and verify the exception
|
||||||
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> {
|
DataSourceException exception = assertThrows(DataSourceException.class, () -> {
|
||||||
dataSource.getProductDTOById(demoProductId);
|
dataSource.getProductDTOById(demoProductId);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Verify the exception message
|
// Verify the exception message
|
||||||
assertEquals("Couldn't fulfill Amazon API request", exception.getMessage());
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,33 +1,56 @@
|
|||||||
package de.rwu.easydrop.api.dto;
|
package de.rwu.easydrop.api.dto;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
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;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
class ProductDTOTest {
|
class ProductDTOTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testToString1() {
|
void constructor_SetsProductIdAndDataOrigin() {
|
||||||
ProductDTO product1 = new ProductDTO("12345", "Amazon");
|
// Arrange
|
||||||
product1.setMerchant("Merchant A");
|
String productId = "12345";
|
||||||
product1.setCurrentPrice(19.99);
|
String dataOrigin = "Amazon";
|
||||||
product1.setAvailable(true);
|
|
||||||
|
|
||||||
String expectedString1 = "ProductDTO{12345 from Merchant A (Amazon) at 19,99 € (available: yes)}";
|
// Act
|
||||||
String result1 = product1.toString();
|
ProductDTO productDTO = new ProductDTO(productId, dataOrigin);
|
||||||
|
|
||||||
assertEquals(expectedString1, result1);
|
// Assert
|
||||||
|
assertEquals(productId, productDTO.getProductId());
|
||||||
|
assertEquals(dataOrigin, productDTO.getDataOrigin());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testToString2() {
|
void gettersAndSetters_WorkAsExpected() {
|
||||||
ProductDTO product2 = new ProductDTO("67890", "eBay");
|
// Arrange
|
||||||
product2.setMerchant("Merchant B");
|
ProductDTO productDTO = new ProductDTO("12345", "Amazon");
|
||||||
product2.setCurrentPrice(9.99);
|
|
||||||
product2.setAvailable(false);
|
|
||||||
|
|
||||||
String expectedString2 = "ProductDTO{67890 from Merchant B (eBay) at 9,99 € (available: no)}";
|
// Act and Assert
|
||||||
String result2 = product2.toString();
|
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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
75
src/test/java/de/rwu/easydrop/model/ProductTest.java
Normal file
75
src/test/java/de/rwu/easydrop/model/ProductTest.java
Normal file
@@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<ProductMapper> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<ProductValidator> 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<Product> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package de.rwu.easydrop.util;
|
package de.rwu.easydrop.util;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
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.assertThrows;
|
||||||
import static org.junit.jupiter.api.Assertions.fail;
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
@@ -13,7 +14,7 @@ import org.junit.jupiter.api.Test;
|
|||||||
|
|
||||||
class ConfigImplTest {
|
class ConfigImplTest {
|
||||||
private Config config;
|
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_KEY = "API_KEY";
|
||||||
private final static String TESTDATA_VAL = "keyIsHere";
|
private final static String TESTDATA_VAL = "keyIsHere";
|
||||||
|
|
||||||
@@ -34,7 +35,9 @@ class ConfigImplTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testGetProperty_ConfigNotLoaded() {
|
void testGetProperty_ConfigNotLoaded() throws Exception {
|
||||||
|
config.reset();
|
||||||
|
|
||||||
NoSuchElementException exception = assertThrows(NoSuchElementException.class, () -> {
|
NoSuchElementException exception = assertThrows(NoSuchElementException.class, () -> {
|
||||||
config.getProperty(TESTDATA_KEY);
|
config.getProperty(TESTDATA_KEY);
|
||||||
});
|
});
|
||||||
@@ -74,7 +77,7 @@ class ConfigImplTest {
|
|||||||
@Test
|
@Test
|
||||||
void testLoadConfigSuccessfully() {
|
void testLoadConfigSuccessfully() {
|
||||||
try {
|
try {
|
||||||
config.setConfigLocation("testResources/testdata.properties");
|
config.setConfigLocation("src/test/resources/testdata.properties");
|
||||||
config.loadConfig();
|
config.loadConfig();
|
||||||
assertEquals(TESTDATA_VAL, config.getProperty(TESTDATA_KEY));
|
assertEquals(TESTDATA_VAL, config.getProperty(TESTDATA_KEY));
|
||||||
} catch (ConfigurationException e) {
|
} catch (ConfigurationException e) {
|
||||||
@@ -92,4 +95,19 @@ class ConfigImplTest {
|
|||||||
|
|
||||||
assertEquals("Couldn't load required config file", exception.getMessage());
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package de.rwu.easydrop.util;
|
|||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||||
import static org.mockito.Mockito.spy;
|
import static org.mockito.Mockito.spy;
|
||||||
|
|
||||||
import javax.naming.ConfigurationException;
|
import javax.naming.ConfigurationException;
|
||||||
@@ -20,17 +21,18 @@ class ConfigTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testGetInstanceNull() {
|
void testGetInstance() {
|
||||||
config = null;
|
|
||||||
|
|
||||||
Config newConfig = Config.getInstance();
|
Config newConfig = Config.getInstance();
|
||||||
assertNotNull(newConfig);
|
assertNotNull(newConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testGetInstanceNotNull() {
|
void testGetInstanceEquality() {
|
||||||
Config newConfig = Config.getInstance();
|
// Create "two" instances to check validity of Singleton pattern
|
||||||
assertNotNull(newConfig);
|
Config instance1 = Config.getInstance();
|
||||||
|
Config instance2 = Config.getInstance();
|
||||||
|
|
||||||
|
assertSame(instance1, instance2, "Instances should be equal");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
1
src/test/resources/empty.properties
Normal file
1
src/test/resources/empty.properties
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
5
src/test/resources/testdata.properties
Normal file
5
src/test/resources/testdata.properties
Normal file
@@ -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
|
||||||
@@ -1 +0,0 @@
|
|||||||
API_KEY=keyIsHere
|
|
||||||
Reference in New Issue
Block a user