Merge branch '#75-Transactions' into 'dev'
Merge feature branches Offers/Transactions See merge request team1/sandbox2!11
This commit is contained in:
@@ -3,3 +3,4 @@ AMAZON_API_URL=
|
||||
AMAZON_API_KEY=
|
||||
EBAY_API_URL=
|
||||
EBAY_API_KEY=
|
||||
WEBSHOPS=amazon,ebay
|
||||
@@ -5,10 +5,10 @@
|
||||
"description": "Very epic GPU",
|
||||
"identifiers": [
|
||||
{
|
||||
"Amazon": "B096Y2TYKV"
|
||||
"AMAZON": "B096Y2TYKV"
|
||||
},
|
||||
{
|
||||
"eBay": "Gigabyte GeForce RTX 3060"
|
||||
"EBAY": "Gigabyte GeForce RTX 3060"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -9,3 +9,4 @@ services:
|
||||
image: easydrop:0.3.0-SNAPSHOT
|
||||
volumes:
|
||||
- ./config:/config
|
||||
- ./persistence.db:/persistence.db
|
||||
|
||||
@@ -1,23 +1,8 @@
|
||||
package de.rwu.easydrop;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.sqlite.SQLiteDataSource;
|
||||
|
||||
import de.rwu.easydrop.api.client.DataSourceFactory;
|
||||
import de.rwu.easydrop.data.connector.AbstractProductPersistence;
|
||||
import de.rwu.easydrop.data.connector.SQLiteConnector;
|
||||
import de.rwu.easydrop.model.ProductCatalogue;
|
||||
import de.rwu.easydrop.service.processing.OrderManager;
|
||||
import de.rwu.easydrop.service.retriever.CatalogueRetriever;
|
||||
import de.rwu.easydrop.service.retriever.ProductRetriever;
|
||||
import de.rwu.easydrop.service.writer.CatalogueWriter;
|
||||
import de.rwu.easydrop.util.Config;
|
||||
import de.rwu.easydrop.util.ProductsConfig;
|
||||
import de.rwu.easydrop.core.Core;
|
||||
|
||||
/**
|
||||
* Kickoff point for the service.
|
||||
@@ -25,11 +10,6 @@ import de.rwu.easydrop.util.ProductsConfig;
|
||||
* @since 0.1.0
|
||||
*/
|
||||
public final class Main {
|
||||
/**
|
||||
* Logger for main process.
|
||||
*/
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(Main.class);
|
||||
|
||||
/**
|
||||
* Prevents unwanted instantiation.
|
||||
*/
|
||||
@@ -43,23 +23,6 @@ public final class Main {
|
||||
* @param args
|
||||
*/
|
||||
public static void main(final String[] args) throws ConfigurationException {
|
||||
Config config = Config.getInstance();
|
||||
ProductsConfig pConfig = ProductsConfig.getInstance();
|
||||
DataSourceFactory dataSourceFactory = new DataSourceFactory(config);
|
||||
ProductRetriever retriever = new ProductRetriever(dataSourceFactory);
|
||||
CatalogueRetriever catRetriever = new CatalogueRetriever(pConfig, retriever);
|
||||
AbstractProductPersistence db = new SQLiteConnector(new SQLiteDataSource());
|
||||
CatalogueWriter catWriter = new CatalogueWriter(db);
|
||||
|
||||
catRetriever.loadCatalogues();
|
||||
List<ProductCatalogue> pCats = catRetriever.getProductCatalogues();
|
||||
catWriter.writeCatalogues(pCats);
|
||||
|
||||
for (ProductCatalogue pCat : pCats) {
|
||||
String pCatStr = pCat.toString();
|
||||
LOGGER.info(pCatStr);
|
||||
}
|
||||
|
||||
OrderManager.createOrders(pCats);
|
||||
Core.run();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import java.net.URL;
|
||||
|
||||
import de.rwu.easydrop.api.dto.ProductDTO;
|
||||
import de.rwu.easydrop.exception.DataSourceException;
|
||||
import de.rwu.easydrop.model.Webshop;
|
||||
import de.rwu.easydrop.util.FormattingUtil;
|
||||
|
||||
/**
|
||||
@@ -23,7 +24,7 @@ public abstract class AbstractDataSource implements DataSource {
|
||||
*
|
||||
* @return Data source name
|
||||
*/
|
||||
protected abstract String getDataOrigin();
|
||||
protected abstract Webshop getDataOrigin();
|
||||
|
||||
/**
|
||||
* Returns the data source's API key.
|
||||
@@ -48,7 +49,7 @@ public abstract class AbstractDataSource implements DataSource {
|
||||
public ProductDTO getProductDTOById(final String productIdentifier)
|
||||
throws IllegalArgumentException {
|
||||
StringBuilder response = new StringBuilder();
|
||||
String dataOrigin = getDataOrigin();
|
||||
Webshop dataOrigin = getDataOrigin();
|
||||
String apiKey = getApiKey();
|
||||
ProductDTO product = new ProductDTO(productIdentifier, dataOrigin);
|
||||
|
||||
@@ -78,7 +79,13 @@ public abstract class AbstractDataSource implements DataSource {
|
||||
}
|
||||
reader.close();
|
||||
|
||||
buildProductDTO(product, response.toString());
|
||||
String data;
|
||||
if (response.toString().isEmpty()) {
|
||||
data = "{}";
|
||||
} else {
|
||||
data = response.toString();
|
||||
}
|
||||
buildProductDTO(product, data);
|
||||
} catch (IOException e) {
|
||||
throw new DataSourceException(
|
||||
"Couldn't fulfill "
|
||||
|
||||
@@ -7,6 +7,7 @@ import java.net.URL;
|
||||
|
||||
import de.rwu.easydrop.api.dto.ProductDTO;
|
||||
import de.rwu.easydrop.exception.DataWriterException;
|
||||
import de.rwu.easydrop.model.Webshop;
|
||||
import de.rwu.easydrop.util.FormattingUtil;
|
||||
|
||||
/**
|
||||
@@ -28,7 +29,7 @@ public abstract class AbstractDataWriter {
|
||||
*
|
||||
* @return Data target API name
|
||||
*/
|
||||
protected abstract String getDataTarget();
|
||||
protected abstract Webshop getDataTarget();
|
||||
|
||||
/**
|
||||
* Creates an URL object to connect to the API with.
|
||||
@@ -47,7 +48,7 @@ public abstract class AbstractDataWriter {
|
||||
*/
|
||||
protected void sendPutRequest(final ProductDTO dto, final String apiType) {
|
||||
String apiKey = getApiKey();
|
||||
String dataTarget = getDataTarget();
|
||||
Webshop dataTarget = getDataTarget();
|
||||
|
||||
if (!dataTarget.equals(dto.getDataOrigin())) {
|
||||
throw new DataWriterException(
|
||||
|
||||
@@ -8,6 +8,8 @@ import com.jayway.jsonpath.PathNotFoundException;
|
||||
import com.jayway.jsonpath.ReadContext;
|
||||
|
||||
import de.rwu.easydrop.api.dto.ProductDTO;
|
||||
import de.rwu.easydrop.model.Webshop;
|
||||
import de.rwu.easydrop.util.Timestamp;
|
||||
|
||||
/**
|
||||
* Interface to an Amazon data source.
|
||||
@@ -18,7 +20,7 @@ public final class AmazonProductDataSource extends AbstractDataSource {
|
||||
/**
|
||||
* Name of this data source.
|
||||
*/
|
||||
private static final String DATA_ORIGIN = "Amazon";
|
||||
private static final Webshop DATA_ORIGIN = Webshop.AMAZON;
|
||||
/**
|
||||
* Base URL to the Amazon data source.
|
||||
*/
|
||||
@@ -60,6 +62,7 @@ public final class AmazonProductDataSource extends AbstractDataSource {
|
||||
product.setDeliveryPrice(
|
||||
ctx.read(root + "shippingOptions[0].shippingCost.value.amount", double.class));
|
||||
product.setMerchant(ctx.read(root + "merchant.name", String.class));
|
||||
product.setLastUpdate(Timestamp.now());
|
||||
} catch (PathNotFoundException e) {
|
||||
// Pass, allow incomplete ProductDTO to pass for later validation
|
||||
}
|
||||
@@ -82,7 +85,7 @@ public final class AmazonProductDataSource extends AbstractDataSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDataOrigin() {
|
||||
protected Webshop getDataOrigin() {
|
||||
return DATA_ORIGIN;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@ package de.rwu.easydrop.api.client;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
import de.rwu.easydrop.model.Webshop;
|
||||
|
||||
/**
|
||||
* Sends a buy request to the Amazon API.
|
||||
*
|
||||
@@ -12,7 +14,7 @@ public final class AmazonPurchaser extends AbstractPurchaser {
|
||||
/**
|
||||
* Name of this data source.
|
||||
*/
|
||||
private static final String DATA_TARGET = "Amazon";
|
||||
private static final Webshop DATA_TARGET = Webshop.AMAZON;
|
||||
/**
|
||||
* Base URL to the Amazon Purchase API.
|
||||
*/
|
||||
@@ -61,7 +63,7 @@ public final class AmazonPurchaser extends AbstractPurchaser {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDataTarget() {
|
||||
protected Webshop getDataTarget() {
|
||||
return DATA_TARGET;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ package de.rwu.easydrop.api.client;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
import de.rwu.easydrop.model.Webshop;
|
||||
|
||||
/**
|
||||
* Sends a sell request to the Amazon API.
|
||||
*
|
||||
@@ -12,7 +14,7 @@ public final class AmazonSeller extends AbstractSeller {
|
||||
/**
|
||||
* Name of this data source.
|
||||
*/
|
||||
private static final String DATA_TARGET = "Amazon";
|
||||
private static final Webshop DATA_TARGET = Webshop.AMAZON;
|
||||
/**
|
||||
* Base URL to the Amazon Purchase API.
|
||||
*/
|
||||
@@ -61,7 +63,7 @@ public final class AmazonSeller extends AbstractSeller {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDataTarget() {
|
||||
protected Webshop getDataTarget() {
|
||||
return DATA_TARGET;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@ package de.rwu.easydrop.api.client;
|
||||
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import de.rwu.easydrop.data.connector.AbstractProductPersistence;
|
||||
import de.rwu.easydrop.exception.PersistenceException;
|
||||
import de.rwu.easydrop.util.Config;
|
||||
|
||||
/**
|
||||
@@ -17,17 +15,6 @@ public class DataSourceFactory {
|
||||
* The data source config.
|
||||
*/
|
||||
private Config config;
|
||||
/**
|
||||
* Persistence interface.
|
||||
*/
|
||||
private AbstractProductPersistence persistence = null;
|
||||
|
||||
/**
|
||||
* @param newPersistence the persistence to set
|
||||
*/
|
||||
public void setPersistence(final AbstractProductPersistence newPersistence) {
|
||||
this.persistence = newPersistence;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param newConfig the config to set
|
||||
@@ -65,17 +52,4 @@ public class DataSourceFactory {
|
||||
String apiKey = config.getProperty("EBAY_API_KEY");
|
||||
return new EbayItemDataSource(apiUrl, apiKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a persistence data source.
|
||||
*
|
||||
* @return ProductPersistenceInterface
|
||||
*/
|
||||
public AbstractProductPersistence createProductPersistenceDataSource() {
|
||||
if (persistence == null) {
|
||||
throw new PersistenceException("Persistence is not set");
|
||||
}
|
||||
|
||||
return persistence;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ import com.jayway.jsonpath.PathNotFoundException;
|
||||
import com.jayway.jsonpath.ReadContext;
|
||||
|
||||
import de.rwu.easydrop.api.dto.ProductDTO;
|
||||
import de.rwu.easydrop.model.Webshop;
|
||||
import de.rwu.easydrop.util.Timestamp;
|
||||
|
||||
/**
|
||||
* Interface to an eBay data source.
|
||||
@@ -18,7 +20,7 @@ public final class EbayItemDataSource extends AbstractDataSource {
|
||||
/**
|
||||
* Name of this data source.
|
||||
*/
|
||||
private static final String DATA_ORIGIN = "eBay";
|
||||
private static final Webshop DATA_ORIGIN = Webshop.EBAY;
|
||||
/**
|
||||
* Base URL to the eBay data source.
|
||||
*/
|
||||
@@ -69,6 +71,7 @@ public final class EbayItemDataSource extends AbstractDataSource {
|
||||
product.setDeliveryPrice(
|
||||
ctx.read(root + "shippingOptions[0].shippingCost.value", double.class));
|
||||
product.setMerchant(ctx.read(root + "seller.username", String.class));
|
||||
product.setLastUpdate(Timestamp.now());
|
||||
} catch (PathNotFoundException e) {
|
||||
// Pass, allow incomplete ProductDTO to pass for later validation
|
||||
}
|
||||
@@ -77,7 +80,7 @@ public final class EbayItemDataSource extends AbstractDataSource {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDataOrigin() {
|
||||
protected Webshop getDataOrigin() {
|
||||
return DATA_ORIGIN;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@ package de.rwu.easydrop.api.client;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
import de.rwu.easydrop.model.Webshop;
|
||||
|
||||
/**
|
||||
* Sends a buy request to the eBay API.
|
||||
*
|
||||
@@ -12,7 +14,7 @@ public final class EbayPurchaser extends AbstractPurchaser {
|
||||
/**
|
||||
* Name of this data source.
|
||||
*/
|
||||
private static final String DATA_TARGET = "eBay";
|
||||
private static final Webshop DATA_TARGET = Webshop.EBAY;
|
||||
/**
|
||||
* Base URL to the eBay Purchase API.
|
||||
*/
|
||||
@@ -46,7 +48,7 @@ public final class EbayPurchaser extends AbstractPurchaser {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDataTarget() {
|
||||
protected Webshop getDataTarget() {
|
||||
return DATA_TARGET;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ package de.rwu.easydrop.api.client;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
import de.rwu.easydrop.model.Webshop;
|
||||
|
||||
/**
|
||||
* Sends a sell request to the eBay API.
|
||||
*
|
||||
@@ -12,7 +14,7 @@ public final class EbaySeller extends AbstractSeller {
|
||||
/**
|
||||
* Name of this data source.
|
||||
*/
|
||||
private static final String DATA_TARGET = "eBay";
|
||||
private static final Webshop DATA_TARGET = Webshop.EBAY;
|
||||
/**
|
||||
* Base URL to the eBay Purchase API.
|
||||
*/
|
||||
@@ -46,7 +48,7 @@ public final class EbaySeller extends AbstractSeller {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDataTarget() {
|
||||
protected Webshop getDataTarget() {
|
||||
return DATA_TARGET;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
package de.rwu.easydrop.api.client;
|
||||
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import de.rwu.easydrop.util.Config;
|
||||
|
||||
/**
|
||||
* Factory for Buyer API accessors.
|
||||
*
|
||||
* @since 0.3.0
|
||||
*/
|
||||
public class PurchaserFactory {
|
||||
|
||||
/**
|
||||
* 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 PurchaserFactory(final Config newConfig) throws ConfigurationException {
|
||||
this.setConfig(newConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an Amazon purchaser.
|
||||
*
|
||||
* @return AmazonPurchaser
|
||||
*/
|
||||
public AmazonPurchaser createAmazonPurchaser() {
|
||||
String apiUrl = config.getProperty("AMAZON_API_URL");
|
||||
String apiKey = config.getProperty("AMAZON_API_KEY");
|
||||
return new AmazonPurchaser(apiUrl, apiKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an eBay purchaser.
|
||||
*
|
||||
* @return EbayPurchaser
|
||||
*/
|
||||
public EbayPurchaser createEbayPurchaser() {
|
||||
String apiUrl = config.getProperty("EBAY_API_URL");
|
||||
String apiKey = config.getProperty("EBAY_API_KEY");
|
||||
return new EbayPurchaser(apiUrl, apiKey);
|
||||
}
|
||||
}
|
||||
55
src/main/java/de/rwu/easydrop/api/client/SellerFactory.java
Normal file
55
src/main/java/de/rwu/easydrop/api/client/SellerFactory.java
Normal file
@@ -0,0 +1,55 @@
|
||||
package de.rwu.easydrop.api.client;
|
||||
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import de.rwu.easydrop.util.Config;
|
||||
|
||||
/**
|
||||
* Factory for Sales API accessors.
|
||||
*
|
||||
* @since 0.3.0
|
||||
*/
|
||||
public class SellerFactory {
|
||||
|
||||
/**
|
||||
* 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 SellerFactory(final Config newConfig) throws ConfigurationException {
|
||||
this.setConfig(newConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an Amazon Seller.
|
||||
*
|
||||
* @return AmazonSeller
|
||||
*/
|
||||
public AmazonSeller createAmazonSeller() {
|
||||
String apiUrl = config.getProperty("AMAZON_API_URL");
|
||||
String apiKey = config.getProperty("AMAZON_API_KEY");
|
||||
return new AmazonSeller(apiUrl, apiKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an eBay Seller.
|
||||
*
|
||||
* @return EbaySeller
|
||||
*/
|
||||
public EbaySeller createEbaySeller() {
|
||||
String apiUrl = config.getProperty("EBAY_API_URL");
|
||||
String apiKey = config.getProperty("EBAY_API_KEY");
|
||||
return new EbaySeller(apiUrl, apiKey);
|
||||
}
|
||||
}
|
||||
33
src/main/java/de/rwu/easydrop/api/dto/OfferDTO.java
Normal file
33
src/main/java/de/rwu/easydrop/api/dto/OfferDTO.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package de.rwu.easydrop.api.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/*
|
||||
* Offer data transfer object.
|
||||
*
|
||||
* @since 0.3.0
|
||||
*/
|
||||
@Data
|
||||
public class OfferDTO {
|
||||
/**
|
||||
* ID of the offer, built from identifiers of the source platforms.
|
||||
*/
|
||||
private String offerId;
|
||||
|
||||
/**
|
||||
* The product that our software buys.
|
||||
*/
|
||||
private ProductDTO sourceProduct;
|
||||
|
||||
/**
|
||||
* The product that our software sells.
|
||||
*/
|
||||
private ProductDTO targetProduct;
|
||||
|
||||
/**
|
||||
* Date of last update of the offer.
|
||||
*/
|
||||
private String lastUpdate;
|
||||
|
||||
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package de.rwu.easydrop.api.dto;
|
||||
|
||||
import de.rwu.easydrop.model.Webshop;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
@@ -10,9 +11,9 @@ import lombok.Data;
|
||||
@Data
|
||||
public class ProductDTO {
|
||||
/**
|
||||
* Data source platform, like "Amazon".
|
||||
* Data source platform, like Amazon.
|
||||
*/
|
||||
private String dataOrigin;
|
||||
private Webshop dataOrigin;
|
||||
|
||||
/**
|
||||
* Platform internal product identifier.
|
||||
@@ -39,13 +40,18 @@ public class ProductDTO {
|
||||
*/
|
||||
private boolean available;
|
||||
|
||||
/**
|
||||
* Last update from API.
|
||||
*/
|
||||
private String lastUpdate;
|
||||
|
||||
/**
|
||||
* Creates ProductDTO instance.
|
||||
*
|
||||
* @param newProductId Internal Product indetifier
|
||||
* @param newDataOrigin Data Origin
|
||||
*/
|
||||
public ProductDTO(final String newProductId, final String newDataOrigin) {
|
||||
public ProductDTO(final String newProductId, final Webshop newDataOrigin) {
|
||||
this.productId = newProductId;
|
||||
this.dataOrigin = newDataOrigin;
|
||||
}
|
||||
|
||||
28
src/main/java/de/rwu/easydrop/api/dto/TransactionDTO.java
Normal file
28
src/main/java/de/rwu/easydrop/api/dto/TransactionDTO.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package de.rwu.easydrop.api.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* Transaction data transfer object.
|
||||
*
|
||||
* @since 0.3.0
|
||||
*/
|
||||
@Data
|
||||
public class TransactionDTO {
|
||||
/**
|
||||
* Offer ID.
|
||||
*/
|
||||
private String offerId;
|
||||
/**
|
||||
* Sales volume.
|
||||
*/
|
||||
private double volume;
|
||||
/**
|
||||
* Earnings (volume - cost).
|
||||
*/
|
||||
private double earnings;
|
||||
/**
|
||||
* Transaction timestamp.
|
||||
*/
|
||||
private String transactionTime;
|
||||
}
|
||||
92
src/main/java/de/rwu/easydrop/core/Core.java
Normal file
92
src/main/java/de/rwu/easydrop/core/Core.java
Normal file
@@ -0,0 +1,92 @@
|
||||
package de.rwu.easydrop.core;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.sqlite.SQLiteDataSource;
|
||||
|
||||
import de.rwu.easydrop.api.client.DataSourceFactory;
|
||||
import de.rwu.easydrop.api.client.PurchaserFactory;
|
||||
import de.rwu.easydrop.api.client.SellerFactory;
|
||||
import de.rwu.easydrop.api.dto.OfferDTO;
|
||||
import de.rwu.easydrop.data.connector.OfferPersistenceInterface;
|
||||
import de.rwu.easydrop.data.connector.ProductPersistenceInterface;
|
||||
import de.rwu.easydrop.data.connector.SQLiteConnector;
|
||||
import de.rwu.easydrop.data.connector.TransactionPersistenceInterface;
|
||||
import de.rwu.easydrop.model.Offer;
|
||||
import de.rwu.easydrop.model.ProductCatalogue;
|
||||
import de.rwu.easydrop.service.mapping.OfferMapper;
|
||||
import de.rwu.easydrop.service.processing.OfferIdentifier;
|
||||
import de.rwu.easydrop.service.processing.OfferProvisioner;
|
||||
import de.rwu.easydrop.service.processing.TransactionHandler;
|
||||
import de.rwu.easydrop.service.retriever.CatalogueRetriever;
|
||||
import de.rwu.easydrop.service.retriever.ProductRetriever;
|
||||
import de.rwu.easydrop.service.writer.CatalogueWriter;
|
||||
import de.rwu.easydrop.util.Config;
|
||||
import de.rwu.easydrop.util.ProductsConfig;
|
||||
|
||||
/**
|
||||
* The application core.
|
||||
*
|
||||
* @since 0.3.0
|
||||
*/
|
||||
public final class Core {
|
||||
/**
|
||||
* Logging instance.
|
||||
*/
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(Core.class);
|
||||
|
||||
/**
|
||||
* Hidden Constructor.
|
||||
*/
|
||||
private Core() {
|
||||
// Hidden constructor
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the core.
|
||||
*
|
||||
* @throws ConfigurationException
|
||||
*/
|
||||
public static void run() throws ConfigurationException {
|
||||
LOGGER.info("Loading config...");
|
||||
Config config = Config.getInstance();
|
||||
ProductsConfig pConfig = ProductsConfig.getInstance();
|
||||
|
||||
LOGGER.info("Preparing...");
|
||||
DataSourceFactory dataSourceFactory = new DataSourceFactory(config);
|
||||
SellerFactory sellerFactory = new SellerFactory(config);
|
||||
PurchaserFactory purchaserFactory = new PurchaserFactory(config);
|
||||
|
||||
ProductPersistenceInterface productDB = new SQLiteConnector(new SQLiteDataSource());
|
||||
OfferPersistenceInterface offerDB = new SQLiteConnector(new SQLiteDataSource());
|
||||
TransactionPersistenceInterface txDB = new SQLiteConnector(new SQLiteDataSource());
|
||||
|
||||
ProductRetriever retriever = new ProductRetriever(dataSourceFactory, productDB);
|
||||
CatalogueRetriever catRetriever = new CatalogueRetriever(pConfig, retriever);
|
||||
CatalogueWriter catWriter = new CatalogueWriter(productDB);
|
||||
|
||||
LOGGER.info("Loading catalogues");
|
||||
catRetriever.loadCatalogues();
|
||||
List<ProductCatalogue> pCats = catRetriever.getProductCatalogues();
|
||||
catWriter.writeCatalogues(pCats);
|
||||
|
||||
LOGGER.info("Creating offers");
|
||||
OfferIdentifier ident = new OfferIdentifier();
|
||||
OfferProvisioner provis = new OfferProvisioner(offerDB, sellerFactory, purchaserFactory);
|
||||
List<Offer> identifiedOffers = ident.runIdentifier(pCats);
|
||||
provis.runProvisioner(identifiedOffers);
|
||||
|
||||
LOGGER.info("Creating transactions");
|
||||
TransactionHandler txHandler = new TransactionHandler(txDB);
|
||||
for (OfferDTO o : offerDB.getOffers()) {
|
||||
txHandler.turnOfferToTransaction(OfferMapper.mapOfferFromDTO(o));
|
||||
}
|
||||
|
||||
txDB.outputTransactionsToLog();
|
||||
txDB.outputSummaryToLog();
|
||||
}
|
||||
}
|
||||
6
src/main/java/de/rwu/easydrop/core/package-info.java
Normal file
6
src/main/java/de/rwu/easydrop/core/package-info.java
Normal file
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* EasyDrop's core.
|
||||
*
|
||||
* @since 0.3.0
|
||||
*/
|
||||
package de.rwu.easydrop.core;
|
||||
@@ -1,34 +0,0 @@
|
||||
package de.rwu.easydrop.data.connector;
|
||||
|
||||
import de.rwu.easydrop.api.client.AbstractDataSource;
|
||||
import de.rwu.easydrop.api.dto.ProductDTO;
|
||||
|
||||
/**
|
||||
* Allows connecting to a persistent product data store.
|
||||
*
|
||||
* @since 0.2.0
|
||||
*/
|
||||
public abstract class AbstractProductPersistence extends AbstractDataSource {
|
||||
/**
|
||||
* Data origin.
|
||||
*/
|
||||
public static final String DATA_ORIGIN = "Persistence";
|
||||
|
||||
/**
|
||||
* Writes a ProductDTO to persistence.
|
||||
*
|
||||
* @param dto
|
||||
*/
|
||||
public abstract void saveProduct(ProductDTO dto);
|
||||
|
||||
/**
|
||||
* Gets a ProductDTO from persistence.
|
||||
*/
|
||||
@Override
|
||||
public abstract ProductDTO getProductDTOById(String productId);
|
||||
|
||||
/**
|
||||
* Deletes all data from persistence.
|
||||
*/
|
||||
public abstract void clearData();
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package de.rwu.easydrop.data.connector;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import de.rwu.easydrop.api.dto.OfferDTO;
|
||||
|
||||
/**
|
||||
* Interface to offer persistence.
|
||||
*
|
||||
* @since 0.3.0
|
||||
*/
|
||||
public interface OfferPersistenceInterface {
|
||||
/**
|
||||
* Writes a ProductDTO to persistence.
|
||||
*
|
||||
* @param dto
|
||||
*/
|
||||
void writeOffer(OfferDTO dto);
|
||||
|
||||
/**
|
||||
* Gets a OfferDTO from persistence.
|
||||
*
|
||||
* @param offerId
|
||||
* @return Offer data transfer object
|
||||
*/
|
||||
OfferDTO getOfferDTOById(String offerId);
|
||||
|
||||
/**
|
||||
* Gets all offerDTOs from persistence.
|
||||
*
|
||||
* @return offerDTOs
|
||||
*/
|
||||
List<OfferDTO> getOffers();
|
||||
|
||||
/**
|
||||
* Deletes all offer data from persistence.
|
||||
*/
|
||||
void clearOfferData();
|
||||
|
||||
/**
|
||||
* Deletes an offer from persistence.
|
||||
*
|
||||
* @param offerId
|
||||
*/
|
||||
void deleteOfferById(String offerId);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package de.rwu.easydrop.data.connector;
|
||||
|
||||
import de.rwu.easydrop.api.dto.ProductDTO;
|
||||
|
||||
/**
|
||||
* Allows connecting to a persistent product data store.
|
||||
*
|
||||
* @since 0.2.0
|
||||
*/
|
||||
public interface ProductPersistenceInterface {
|
||||
/**
|
||||
* Writes a ProductDTO to persistence.
|
||||
*
|
||||
* @param dto
|
||||
*/
|
||||
void writeProduct(ProductDTO dto);
|
||||
|
||||
/**
|
||||
* Gets a ProductDTO from persistence.
|
||||
*
|
||||
* @param productId Product identifier
|
||||
* @return Product data transfer object
|
||||
*/
|
||||
ProductDTO getProductDTOById(String productId);
|
||||
|
||||
/**
|
||||
* Deletes all product data from persistence.
|
||||
*/
|
||||
void clearProductData();
|
||||
}
|
||||
@@ -1,27 +1,41 @@
|
||||
package de.rwu.easydrop.data.connector;
|
||||
|
||||
import java.net.URL;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.sqlite.SQLiteDataSource;
|
||||
|
||||
import de.rwu.easydrop.api.dto.OfferDTO;
|
||||
import de.rwu.easydrop.api.dto.ProductDTO;
|
||||
import de.rwu.easydrop.api.dto.TransactionDTO;
|
||||
import de.rwu.easydrop.exception.PersistenceException;
|
||||
import de.rwu.easydrop.model.Webshop;
|
||||
import de.rwu.easydrop.util.FormattingUtil;
|
||||
|
||||
/**
|
||||
* Allows connecting to a SQLite Database.
|
||||
*
|
||||
* @since 0.2.0
|
||||
*/
|
||||
public final class SQLiteConnector extends AbstractProductPersistence {
|
||||
public final class SQLiteConnector implements
|
||||
ProductPersistenceInterface, OfferPersistenceInterface,
|
||||
TransactionPersistenceInterface {
|
||||
/**
|
||||
* Data origin.
|
||||
* Base for calculating percentages.
|
||||
*/
|
||||
private static final String DATA_ORIGIN = "SQLite";
|
||||
private static final int PERCENT = 100;
|
||||
|
||||
/**
|
||||
* Logging instance.
|
||||
*/
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(SQLiteConnector.class);
|
||||
|
||||
/**
|
||||
* SQLite Database.
|
||||
@@ -39,6 +53,15 @@ public final class SQLiteConnector extends AbstractProductPersistence {
|
||||
* Path to SQLite db file.
|
||||
*/
|
||||
private static final String PERSISTENCE_PATH = "jdbc:sqlite:persistence.db";
|
||||
/**
|
||||
* Name of 'lastUpdate' column.
|
||||
*/
|
||||
private static final String LAST_UPDATE_COL_NAME = "lastUpdate";
|
||||
|
||||
/**
|
||||
* Name of 'offerId' column.
|
||||
*/
|
||||
private static final String OFFERID_COL_NAME = "offerId";
|
||||
|
||||
/**
|
||||
* Creates instance.
|
||||
@@ -57,8 +80,8 @@ public final class SQLiteConnector extends AbstractProductPersistence {
|
||||
Connection connection = db.getConnection();
|
||||
|
||||
// Execute SQL statements to create tables
|
||||
Statement statement = connection.createStatement();
|
||||
statement.execute(
|
||||
Statement createProducts = connection.createStatement();
|
||||
createProducts.execute(
|
||||
"CREATE TABLE IF NOT EXISTS products ("
|
||||
+ "dataOrigin TEXT, "
|
||||
+ "productId TEXT, "
|
||||
@@ -66,12 +89,39 @@ public final class SQLiteConnector extends AbstractProductPersistence {
|
||||
+ "merchant TEXT, "
|
||||
+ "deliveryPrice REAL, "
|
||||
+ "available INT, "
|
||||
+ "lastupdate TEXT, "
|
||||
+ "lastUpdate TEXT, "
|
||||
+ "UNIQUE(productId, dataOrigin) ON CONFLICT REPLACE"
|
||||
+ ")");
|
||||
|
||||
// Close the statement and connection
|
||||
statement.close();
|
||||
// Close the statement
|
||||
createProducts.close();
|
||||
|
||||
Statement createOffers = connection.createStatement();
|
||||
createOffers.execute(
|
||||
"CREATE TABLE IF NOT EXISTS offers ("
|
||||
+ "offerId TEXT, "
|
||||
+ "sourceWebshop TEXT, "
|
||||
+ "sourceId TEXT,"
|
||||
+ "sourcePrice REAL, "
|
||||
+ "targetWebshop TEXT, "
|
||||
+ "targetId TEXT, "
|
||||
+ "targetPrice REAL, "
|
||||
+ "lastUpdate TEXT, "
|
||||
+ "UNIQUE(offerId) ON CONFLICT REPLACE"
|
||||
+ ")");
|
||||
createOffers.close();
|
||||
|
||||
Statement createTransactions = connection.createStatement();
|
||||
createTransactions.execute(
|
||||
"CREATE TABLE IF NOT EXISTS transactions ("
|
||||
+ "offerId TEXT, "
|
||||
+ "earnings REAL, "
|
||||
+ "volume REAL, "
|
||||
+ "transactionTime TEXT"
|
||||
+ ")");
|
||||
createTransactions.close();
|
||||
|
||||
// Close the connection
|
||||
connection.close();
|
||||
} catch (SQLException e) {
|
||||
throw new PersistenceException("Something went wrong while initializing SQLite DB", e);
|
||||
@@ -83,53 +133,64 @@ public final class SQLiteConnector extends AbstractProductPersistence {
|
||||
*
|
||||
* @param dto
|
||||
*/
|
||||
public void saveProduct(final ProductDTO dto) {
|
||||
public void writeProduct(final ProductDTO dto) {
|
||||
String query = "INSERT INTO products ("
|
||||
+ "dataOrigin, productId, currentPrice, merchant, "
|
||||
+ "deliveryPrice, available, lastupdate"
|
||||
+ ") VALUES ("
|
||||
+ "?, ?, ?, ?, ?, ?, datetime('now', 'localtime')"
|
||||
+ "deliveryPrice, available, lastUpdate"
|
||||
+ ") VALUES ( "
|
||||
+ "?, ?, ?, ?, ?, ?, ?"
|
||||
+ ")";
|
||||
|
||||
try (Connection connection = db.getConnection();
|
||||
PreparedStatement statement = connection.prepareStatement(query)) {
|
||||
int index = 0;
|
||||
|
||||
statement.setString(++index, dto.getDataOrigin());
|
||||
statement.setString(++index, dto.getDataOrigin().toString());
|
||||
statement.setString(++index, dto.getProductId());
|
||||
statement.setDouble(++index, dto.getCurrentPrice());
|
||||
statement.setString(++index, dto.getMerchant());
|
||||
statement.setDouble(++index, dto.getDeliveryPrice());
|
||||
statement.setBoolean(++index, dto.isAvailable());
|
||||
statement.setString(++index, dto.getLastUpdate());
|
||||
|
||||
statement.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
throw new PersistenceException("Something went wrong while saving to SQLite", e);
|
||||
throw new PersistenceException(
|
||||
"Something went wrong while saving product to SQLite", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
/**
|
||||
* Gets a ProductDTO by identifier.
|
||||
*
|
||||
* @param productId
|
||||
* @return DTO
|
||||
*/
|
||||
public ProductDTO getProductDTOById(final String productId) {
|
||||
String query = "SELECT * FROM products WHERE productId = ?";
|
||||
ProductDTO dto = null;
|
||||
|
||||
try (Connection connection = db.getConnection();
|
||||
PreparedStatement statement = connection.prepareStatement(query)) {
|
||||
try {
|
||||
Connection connection = db.getConnection();
|
||||
PreparedStatement statement = connection.prepareStatement(query);
|
||||
|
||||
statement.setString(1, productId);
|
||||
|
||||
try (ResultSet resultSet = statement.executeQuery()) {
|
||||
if (resultSet.next()) {
|
||||
dto = new ProductDTO(resultSet.getString("productId"),
|
||||
resultSet.getString("dataOrigin"));
|
||||
Webshop newShop = Webshop.fromString(resultSet.getString("dataOrigin"));
|
||||
|
||||
dto = new ProductDTO(resultSet.getString("productId"), newShop);
|
||||
dto.setCurrentPrice(resultSet.getDouble("currentPrice"));
|
||||
dto.setMerchant(resultSet.getString("merchant"));
|
||||
dto.setDeliveryPrice(resultSet.getDouble("deliveryPrice"));
|
||||
dto.setAvailable(resultSet.getBoolean("available"));
|
||||
dto.setLastUpdate(resultSet.getString(LAST_UPDATE_COL_NAME));
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new PersistenceException("Something went wrong while reading from SQLite", e);
|
||||
throw new PersistenceException(
|
||||
"Something went wrong while reading product from SQLite");
|
||||
}
|
||||
|
||||
return dto;
|
||||
@@ -137,11 +198,201 @@ public final class SQLiteConnector extends AbstractProductPersistence {
|
||||
|
||||
/**
|
||||
* Deletes all data from persistence.
|
||||
*
|
||||
* @throws SQLException
|
||||
*/
|
||||
public void clearData() {
|
||||
clearProductData();
|
||||
clearOfferData();
|
||||
clearTXData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes an offer to persistence.
|
||||
*
|
||||
* @param dto OfferDTO
|
||||
*/
|
||||
public void writeOffer(final OfferDTO dto) {
|
||||
String query = "INSERT INTO offers ("
|
||||
+ "offerId, "
|
||||
+ "sourceWebshop, sourceId, sourcePrice, "
|
||||
+ "targetWebshop, targetId, targetPrice, "
|
||||
+ LAST_UPDATE_COL_NAME
|
||||
+ ") VALUES ("
|
||||
+ "?, ?, ?, ?, ?, ?, ?, ?"
|
||||
+ ")";
|
||||
|
||||
try (Connection connection = db.getConnection();
|
||||
PreparedStatement statement = connection.prepareStatement(query)) {
|
||||
int index = 0;
|
||||
ProductDTO sourceProduct = dto.getSourceProduct();
|
||||
ProductDTO targetProduct = dto.getTargetProduct();
|
||||
|
||||
statement.setString(++index, dto.getOfferId());
|
||||
statement.setString(++index, sourceProduct.getDataOrigin().toString());
|
||||
statement.setString(++index, sourceProduct.getProductId());
|
||||
statement.setDouble(++index, sourceProduct.getCurrentPrice());
|
||||
statement.setString(++index, targetProduct.getDataOrigin().toString());
|
||||
statement.setString(++index, targetProduct.getProductId());
|
||||
statement.setDouble(++index, targetProduct.getCurrentPrice());
|
||||
statement.setString(++index, dto.getLastUpdate());
|
||||
|
||||
statement.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
throw new PersistenceException(
|
||||
"Something went wrong while saving offer to SQLite", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an OfferDTO by identifier.
|
||||
*
|
||||
* @param offerId
|
||||
* @return OfferDTO
|
||||
*/
|
||||
public OfferDTO getOfferDTOById(final String offerId) {
|
||||
String query = "SELECT * FROM offers WHERE offerId = ?";
|
||||
OfferDTO dto = null;
|
||||
|
||||
try (Connection connection = db.getConnection();
|
||||
PreparedStatement statement = connection.prepareStatement(query)) {
|
||||
|
||||
statement.setString(1, offerId);
|
||||
|
||||
try (ResultSet resultSet = statement.executeQuery()) {
|
||||
if (resultSet.next()) {
|
||||
dto = new OfferDTO();
|
||||
ProductDTO srcProduct = getProductDTOById(resultSet.getString("sourceId"));
|
||||
ProductDTO targetProduct = getProductDTOById(resultSet.getString("targetId"));
|
||||
dto.setOfferId(resultSet.getString(OFFERID_COL_NAME));
|
||||
dto.setSourceProduct(srcProduct);
|
||||
dto.setTargetProduct(targetProduct);
|
||||
dto.setLastUpdate(resultSet.getString(LAST_UPDATE_COL_NAME));
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new PersistenceException(
|
||||
"Something went wrong while reading offer from SQLite", e);
|
||||
}
|
||||
|
||||
return dto;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTX(final TransactionDTO dto) {
|
||||
String query = "INSERT INTO transactions ("
|
||||
+ "offerId, volume, earnings, transactionTime"
|
||||
+ ") VALUES ("
|
||||
+ "?, ?, ?, ?"
|
||||
+ ")";
|
||||
|
||||
try (Connection connection = db.getConnection();
|
||||
PreparedStatement statement = connection.prepareStatement(query)) {
|
||||
int index = 0;
|
||||
|
||||
statement.setString(++index, dto.getOfferId());
|
||||
statement.setDouble(++index, dto.getVolume());
|
||||
statement.setDouble(++index, dto.getEarnings());
|
||||
statement.setString(++index, dto.getTransactionTime());
|
||||
|
||||
statement.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
throw new PersistenceException(
|
||||
"Something went wrong while saving transaction to SQLite", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void outputTransactionsToLog() {
|
||||
String query = "SELECT * FROM transactions t "
|
||||
+ "LEFT JOIN offers o ON t.offerId = o.offerId "
|
||||
+ "ORDER BY transactionTime ASC";
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int index = 0;
|
||||
sb.append("Transaction History:");
|
||||
|
||||
try (Connection connection = db.getConnection();
|
||||
PreparedStatement statement = connection.prepareStatement(query)) {
|
||||
|
||||
try (ResultSet resultSet = statement.executeQuery()) {
|
||||
while (resultSet.next()) {
|
||||
sb.append("\n");
|
||||
sb.append(String.format("%3d", ++index));
|
||||
sb.append(String.format(" - %s - ", resultSet.getString("transactionTime")));
|
||||
sb.append(String.format("+%s (%s) - ",
|
||||
FormattingUtil.formatEuro(resultSet.getDouble("earnings")),
|
||||
FormattingUtil.formatEuro(resultSet.getDouble("volume"))));
|
||||
sb.append(String.format("[%s to %s] %s",
|
||||
resultSet.getString("sourceWebshop"),
|
||||
resultSet.getString("targetWebshop"),
|
||||
resultSet.getString(OFFERID_COL_NAME)));
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new PersistenceException(
|
||||
"Something went wrong while reading transaction from SQLite", e);
|
||||
}
|
||||
|
||||
String logString = sb.toString();
|
||||
LOGGER.info(logString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void outputSummaryToLog() {
|
||||
String query = "SELECT SUM(earnings) AS earnings, SUM(volume) AS volume FROM transactions;";
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Summary:\n");
|
||||
|
||||
try (Connection connection = db.getConnection();
|
||||
PreparedStatement statement = connection.prepareStatement(query)) {
|
||||
|
||||
try (ResultSet resultSet = statement.executeQuery()) {
|
||||
if (resultSet.next()) {
|
||||
double earnings = resultSet.getDouble("earnings");
|
||||
double volume = resultSet.getDouble("volume");
|
||||
String avgMargin = String.valueOf(
|
||||
Math.round(earnings / volume * PERCENT)) + "%";
|
||||
|
||||
String earningsFormatted = FormattingUtil.formatEuro(earnings);
|
||||
String volumeFormatted = FormattingUtil.formatEuro(volume);
|
||||
|
||||
sb.append(String.format("Total earnings: %s, ", earningsFormatted));
|
||||
sb.append(String.format("total volume: %s ", volumeFormatted));
|
||||
sb.append(String.format("(average margin %s)", avgMargin));
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new PersistenceException(
|
||||
"Something went wrong while reading transaction summary from SQLite", e);
|
||||
}
|
||||
|
||||
String logString = sb.toString();
|
||||
LOGGER.info(logString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearTXData() {
|
||||
runDeletionQuery("DELETE FROM transactions;");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearOfferData() {
|
||||
runDeletionQuery("DELETE FROM offers;");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearProductData() {
|
||||
runDeletionQuery("DELETE FROM products;");
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes all data using the specified query.
|
||||
*
|
||||
* @param query
|
||||
*/
|
||||
private void runDeletionQuery(final String query) {
|
||||
try (Connection connection = db.getConnection();
|
||||
Statement statement = connection.createStatement()) {
|
||||
String query = "DELETE FROM products";
|
||||
statement.executeUpdate(query);
|
||||
} catch (SQLException e) {
|
||||
throw new PersistenceException("Something went wrong while clearing the database", e);
|
||||
@@ -149,25 +400,46 @@ public final class SQLiteConnector extends AbstractProductPersistence {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDataOrigin() {
|
||||
return DATA_ORIGIN;
|
||||
public void deleteOfferById(final String offerId) {
|
||||
String query = "DELETE FROM offers WHERE offerID = ?;";
|
||||
|
||||
try (Connection connection = db.getConnection();
|
||||
PreparedStatement statement = connection.prepareStatement(query)) {
|
||||
statement.setString(1, offerId);
|
||||
|
||||
statement.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
throw new PersistenceException(
|
||||
"Something went wrong while deleting offer from SQLite", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getApiKey() {
|
||||
throw new UnsupportedOperationException(
|
||||
this.getClass().getName() + " doesn't support getApiKey");
|
||||
public List<OfferDTO> getOffers() {
|
||||
List<OfferDTO> list = new ArrayList<>();
|
||||
String query = "SELECT * FROM offers";
|
||||
|
||||
try (Connection connection = db.getConnection();
|
||||
PreparedStatement statement = connection.prepareStatement(query)) {
|
||||
|
||||
try (ResultSet resultSet = statement.executeQuery()) {
|
||||
while (resultSet.next()) {
|
||||
OfferDTO dto = new OfferDTO();
|
||||
ProductDTO srcProduct = getProductDTOById(resultSet.getString("sourceId"));
|
||||
ProductDTO targetProduct = getProductDTOById(resultSet.getString("targetId"));
|
||||
dto.setOfferId(resultSet.getString(OFFERID_COL_NAME));
|
||||
dto.setSourceProduct(srcProduct);
|
||||
dto.setTargetProduct(targetProduct);
|
||||
dto.setLastUpdate(resultSet.getString(LAST_UPDATE_COL_NAME));
|
||||
|
||||
list.add(dto);
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new PersistenceException(
|
||||
"Something went wrong while reading offers from SQLite", e);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ProductDTO buildProductDTO(final ProductDTO product, final String json) {
|
||||
throw new UnsupportedOperationException(
|
||||
this.getClass().getName() + " doesn't support buildProductDTO");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected URL createApiUrl(final String productIdentifier) {
|
||||
throw new UnsupportedOperationException(
|
||||
this.getClass().getName() + " doesn't support createApiUrl");
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package de.rwu.easydrop.data.connector;
|
||||
|
||||
import de.rwu.easydrop.api.dto.TransactionDTO;
|
||||
|
||||
/**
|
||||
* Persistence interface for transactions.
|
||||
*
|
||||
* @since 0.3.0
|
||||
*/
|
||||
public interface TransactionPersistenceInterface {
|
||||
/**
|
||||
* Writes a ProductDTO to persistence.
|
||||
*
|
||||
* @param dto
|
||||
*/
|
||||
void writeTX(TransactionDTO dto);
|
||||
|
||||
/**
|
||||
* Writes transactions to log.
|
||||
*/
|
||||
void outputTransactionsToLog();
|
||||
|
||||
/**
|
||||
* Writes transaction summary (total volume and earnings) to log.
|
||||
*/
|
||||
void outputSummaryToLog();
|
||||
|
||||
/**
|
||||
* Deletes all transaction data from persistence.
|
||||
*/
|
||||
void clearTXData();
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package de.rwu.easydrop.exception;
|
||||
|
||||
/**
|
||||
* Exception that signifies the data of an Offer are invalid.
|
||||
*
|
||||
* @since 0.3.0
|
||||
*/
|
||||
public class InvalidOfferException extends RuntimeException {
|
||||
/**
|
||||
* Throws an exception that signifies the data of an Offer are invalid.
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public InvalidOfferException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an exception that signifies the data of an Offer are invalid.
|
||||
*
|
||||
* @param message
|
||||
* @param cause
|
||||
*/
|
||||
public InvalidOfferException(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 Transaction are invalid.
|
||||
*
|
||||
* @since 0.3.0
|
||||
*/
|
||||
public class InvalidTransactionException extends RuntimeException {
|
||||
/**
|
||||
* Throws an exception that signifies the data of an Offer are invalid.
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
public InvalidTransactionException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an exception that signifies the data of an Offer are invalid.
|
||||
*
|
||||
* @param message
|
||||
* @param cause
|
||||
*/
|
||||
public InvalidTransactionException(final String message, final Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
31
src/main/java/de/rwu/easydrop/model/Offer.java
Normal file
31
src/main/java/de/rwu/easydrop/model/Offer.java
Normal file
@@ -0,0 +1,31 @@
|
||||
package de.rwu.easydrop.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* An Offer.
|
||||
*
|
||||
* @since 0.3.0
|
||||
*/
|
||||
@Data
|
||||
public class Offer {
|
||||
/**
|
||||
* ID of the offer, built from identifiers of the source platforms.
|
||||
*/
|
||||
private String offerId;
|
||||
|
||||
/**
|
||||
* The product that our software buys.
|
||||
*/
|
||||
private Product sourceProduct;
|
||||
|
||||
/**
|
||||
* The product that our software sells.
|
||||
*/
|
||||
private Product targetProduct;
|
||||
|
||||
/**
|
||||
* Date of last update of the offer.
|
||||
*/
|
||||
private String lastUpdate;
|
||||
}
|
||||
@@ -13,7 +13,7 @@ public class Product {
|
||||
/**
|
||||
* Data source platform, like "Amazon".
|
||||
*/
|
||||
private String dataOrigin;
|
||||
private Webshop dataOrigin;
|
||||
|
||||
/**
|
||||
* Platform internal product identifier.
|
||||
@@ -40,6 +40,11 @@ public class Product {
|
||||
*/
|
||||
private boolean available;
|
||||
|
||||
/**
|
||||
* Last update from API.
|
||||
*/
|
||||
private String lastUpdate;
|
||||
|
||||
@Override
|
||||
public final String toString() {
|
||||
return "Product: ["
|
||||
|
||||
@@ -68,11 +68,11 @@ public class ProductCatalogue {
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Product Catalogue: ").append(productName).append("\n");
|
||||
sb.append("Description: ").append(description).append("\n");
|
||||
sb.append(String.format("Catalogue Name: %s%n", productName));
|
||||
sb.append(String.format("Description: %s%n", description));
|
||||
sb.append("Products:\n");
|
||||
for (Product product : products) {
|
||||
sb.append(product.toString()).append("\n");
|
||||
sb.append(String.format("%s%n", product.toString()));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
30
src/main/java/de/rwu/easydrop/model/Transaction.java
Normal file
30
src/main/java/de/rwu/easydrop/model/Transaction.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package de.rwu.easydrop.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* A transaction.
|
||||
*
|
||||
* @since 0.3.0
|
||||
*/
|
||||
@Data
|
||||
public class Transaction {
|
||||
/**
|
||||
* Offer ID.
|
||||
*
|
||||
* @see Offer
|
||||
*/
|
||||
private String offerId;
|
||||
/**
|
||||
* Sales volume.
|
||||
*/
|
||||
private double volume;
|
||||
/**
|
||||
* Earnings (volume - cost).
|
||||
*/
|
||||
private double earnings;
|
||||
/**
|
||||
* Transaction timestamp.
|
||||
*/
|
||||
private String transactionTime;
|
||||
}
|
||||
31
src/main/java/de/rwu/easydrop/model/Webshop.java
Normal file
31
src/main/java/de/rwu/easydrop/model/Webshop.java
Normal file
@@ -0,0 +1,31 @@
|
||||
package de.rwu.easydrop.model;
|
||||
|
||||
/**
|
||||
* Constants for data source/destination platforms.
|
||||
*/
|
||||
public enum Webshop {
|
||||
/**
|
||||
* Amazon Product API.
|
||||
*/
|
||||
AMAZON,
|
||||
/**
|
||||
* eBay Item API.
|
||||
*/
|
||||
EBAY;
|
||||
|
||||
/**
|
||||
* Attempts to derive a webshop value from a string.
|
||||
*
|
||||
* @param str String
|
||||
* @return webshop
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
public static Webshop fromString(final String str) {
|
||||
for (Webshop shop : Webshop.values()) {
|
||||
if (shop.toString().equalsIgnoreCase(str)) {
|
||||
return shop;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException(String.format("No webshop called %s found", str));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package de.rwu.easydrop.service.mapping;
|
||||
|
||||
import de.rwu.easydrop.api.dto.OfferDTO;
|
||||
import de.rwu.easydrop.model.Offer;
|
||||
|
||||
/**
|
||||
* Maps between Offer, OfferDTO and OfferDTO.
|
||||
*
|
||||
* @since 0.2.0
|
||||
*
|
||||
* @see Offer
|
||||
* @see OfferDTO
|
||||
*/
|
||||
public final class OfferMapper {
|
||||
|
||||
/**
|
||||
* Private constructor to prevent unwanted instantiation.
|
||||
*
|
||||
* @throws UnsupportedOperationException always
|
||||
*/
|
||||
private OfferMapper() throws UnsupportedOperationException {
|
||||
throw new UnsupportedOperationException("This is a mapping class, don't instantiate it.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Offer object from a corresponding DTO.
|
||||
*
|
||||
* @param dto Offer Data Transfer Object
|
||||
* @return Offer
|
||||
*/
|
||||
public static Offer mapOfferFromDTO(final OfferDTO dto) {
|
||||
Offer offer = new Offer();
|
||||
offer.setOfferId(dto.getOfferId());
|
||||
offer.setSourceProduct(ProductMapper.mapProductFromDTO(dto.getSourceProduct()));
|
||||
offer.setTargetProduct(ProductMapper.mapProductFromDTO(dto.getTargetProduct()));
|
||||
offer.setLastUpdate(dto.getLastUpdate());
|
||||
|
||||
return offer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an OfferDTO object from a corresponding offer.
|
||||
*
|
||||
* @param offer
|
||||
* @return OfferDTO
|
||||
*/
|
||||
public static OfferDTO mapOfferToDTO(final Offer offer) {
|
||||
OfferDTO dto = new OfferDTO();
|
||||
dto.setOfferId(offer.getOfferId());
|
||||
dto.setSourceProduct(ProductMapper.mapProductToDTO(offer.getSourceProduct()));
|
||||
dto.setTargetProduct(ProductMapper.mapProductToDTO(offer.getTargetProduct()));
|
||||
dto.setLastUpdate(offer.getLastUpdate());
|
||||
|
||||
return dto;
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,7 @@ public final class ProductMapper {
|
||||
product.setDeliveryPrice(dto.getDeliveryPrice());
|
||||
product.setMerchant(dto.getMerchant());
|
||||
product.setProductId(dto.getProductId());
|
||||
product.setLastUpdate(dto.getLastUpdate());
|
||||
|
||||
return product;
|
||||
}
|
||||
@@ -56,6 +57,7 @@ public final class ProductMapper {
|
||||
dto.setCurrentPrice(product.getCurrentPrice());
|
||||
dto.setDeliveryPrice(product.getDeliveryPrice());
|
||||
dto.setMerchant(product.getMerchant());
|
||||
dto.setLastUpdate(product.getLastUpdate());
|
||||
|
||||
return dto;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package de.rwu.easydrop.service.mapping;
|
||||
|
||||
import de.rwu.easydrop.api.dto.TransactionDTO;
|
||||
import de.rwu.easydrop.model.Transaction;
|
||||
|
||||
/**
|
||||
* Maps transaction DTOs and objects.
|
||||
*
|
||||
* @since 0.3.0
|
||||
*/
|
||||
public final class TransactionMapper {
|
||||
/**
|
||||
* Private constructor to prevent unwanted instantiation.
|
||||
*
|
||||
* @throws UnsupportedOperationException always
|
||||
*/
|
||||
private TransactionMapper() throws UnsupportedOperationException {
|
||||
throw new UnsupportedOperationException("This is a mapping class, don't instantiate it.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Transaction object from a corresponding DTO.
|
||||
*
|
||||
* @param dto Transaction Data Transfer Object
|
||||
* @return Product
|
||||
*/
|
||||
public static Transaction mapTXFromDTO(final TransactionDTO dto) {
|
||||
Transaction tx = new Transaction();
|
||||
|
||||
tx.setOfferId(dto.getOfferId());
|
||||
tx.setVolume(dto.getVolume());
|
||||
tx.setEarnings(dto.getEarnings());
|
||||
tx.setTransactionTime(dto.getTransactionTime());
|
||||
|
||||
return tx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ProductDTO object from a corresponding Product.
|
||||
*
|
||||
* @param tx Transaction
|
||||
* @return TransactionDTO
|
||||
*/
|
||||
public static TransactionDTO mapTXToDTO(final Transaction tx) {
|
||||
TransactionDTO dto = new TransactionDTO();
|
||||
|
||||
dto.setOfferId(tx.getOfferId());
|
||||
dto.setVolume(tx.getVolume());
|
||||
dto.setEarnings(tx.getEarnings());
|
||||
dto.setTransactionTime(tx.getTransactionTime());
|
||||
|
||||
return dto;
|
||||
}
|
||||
}
|
||||
@@ -1,58 +1,62 @@
|
||||
package de.rwu.easydrop.service.processing;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import de.rwu.easydrop.exception.InvalidCatalogueException;
|
||||
import de.rwu.easydrop.exception.InvalidOfferException;
|
||||
import de.rwu.easydrop.model.Offer;
|
||||
import de.rwu.easydrop.model.Product;
|
||||
import de.rwu.easydrop.model.ProductCatalogue;
|
||||
import de.rwu.easydrop.model.ProductPair;
|
||||
import de.rwu.easydrop.util.FormattingUtil;
|
||||
import de.rwu.easydrop.util.Timestamp;
|
||||
|
||||
/**
|
||||
* Creates dropshipping orders based on price margin.
|
||||
*
|
||||
* @since 0.3.0
|
||||
public class OfferIdentifier {
|
||||
/**
|
||||
* Logging instance.
|
||||
*/
|
||||
public final class OrderManager {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(OfferIdentifier.class);
|
||||
|
||||
/**
|
||||
* Temporary logging instance.
|
||||
*/
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(OrderManager.class);
|
||||
|
||||
/**
|
||||
* Private constructor to prevent unwanted instantiation.
|
||||
* runIdentifier calls the price function that decides
|
||||
* if it is feasible to dropship products.
|
||||
*
|
||||
* @throws UnsupportedOperationException always
|
||||
* @param pCats Product catalogues
|
||||
* @return Identified offers
|
||||
*/
|
||||
private OrderManager() throws UnsupportedOperationException {
|
||||
throw new UnsupportedOperationException("This is a stateless class, don't instantiate it.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates orders for products with sufficient margin.
|
||||
*
|
||||
* @param pCats Product Catalogues
|
||||
*/
|
||||
public static void createOrders(final List<ProductCatalogue> pCats) {
|
||||
public List<Offer> runIdentifier(final List<ProductCatalogue> pCats) {
|
||||
List<Offer> identifiedOffers = new ArrayList<>();
|
||||
for (ProductCatalogue pCat : pCats) {
|
||||
ProductPair pair = getHighestMarginProducts(pCat);
|
||||
|
||||
// #12: Create actual orders/transactions, remove logger
|
||||
// Call price finder for all catalogue
|
||||
try {
|
||||
ProductPair pair = getHighestMarginProducts(pCat);
|
||||
Offer possibleOffer = new Offer();
|
||||
possibleOffer.setLastUpdate(Timestamp.now());
|
||||
possibleOffer.setSourceProduct(pair.getProduct1());
|
||||
possibleOffer.setTargetProduct(pair.getProduct2());
|
||||
identifiedOffers.add(possibleOffer);
|
||||
|
||||
double margin = pair.getProduct2().getCurrentPrice()
|
||||
- pair.getProduct1().getCurrentPrice();
|
||||
String marginFormatted = FormattingUtil.formatEuro(margin);
|
||||
LOGGER.info("{}: Margin {} ({} to {})",
|
||||
LOGGER.info("\n Identified Offer: {} ({} to {}) with margin {} ",
|
||||
pCat.getProductName(),
|
||||
marginFormatted,
|
||||
pair.getProduct1().getDataOrigin(),
|
||||
pair.getProduct2().getDataOrigin());
|
||||
pair.getProduct2().getDataOrigin(),
|
||||
marginFormatted);
|
||||
} catch (InvalidOfferException e) {
|
||||
// Don't include offer if deemed invalid
|
||||
}
|
||||
}
|
||||
|
||||
return identifiedOffers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cheapest and most expensive product of a catalogue to guarantee
|
||||
* the biggest margin as a pair.
|
||||
@@ -79,7 +83,7 @@ public final class OrderManager {
|
||||
}
|
||||
|
||||
if (cheapestProduct.getCurrentPrice() == mostExpensiveProduct.getCurrentPrice()) {
|
||||
throw new InvalidCatalogueException("Price margin is zero!");
|
||||
throw new InvalidOfferException("Price margin is zero!");
|
||||
}
|
||||
|
||||
return new ProductPair(cheapestProduct, mostExpensiveProduct);
|
||||
@@ -0,0 +1,115 @@
|
||||
package de.rwu.easydrop.service.processing;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import de.rwu.easydrop.api.client.AmazonPurchaser;
|
||||
import de.rwu.easydrop.api.client.AmazonSeller;
|
||||
import de.rwu.easydrop.api.client.EbayPurchaser;
|
||||
import de.rwu.easydrop.api.client.EbaySeller;
|
||||
import de.rwu.easydrop.api.client.PurchaserFactory;
|
||||
import de.rwu.easydrop.api.client.SellerFactory;
|
||||
import de.rwu.easydrop.data.connector.OfferPersistenceInterface;
|
||||
import de.rwu.easydrop.model.Offer;
|
||||
import de.rwu.easydrop.service.mapping.ProductMapper;
|
||||
import de.rwu.easydrop.service.writer.OfferWriter;
|
||||
import de.rwu.easydrop.util.FormattingUtil;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* Offer provisioner.
|
||||
*
|
||||
* @since 0.3.0
|
||||
*/
|
||||
@Data
|
||||
public class OfferProvisioner {
|
||||
/**
|
||||
* Writes offers into persistence.
|
||||
*/
|
||||
private OfferWriter offerWriter;
|
||||
|
||||
/**
|
||||
* Is the API for selling products on Amazon.
|
||||
*/
|
||||
private AmazonSeller amazonSeller;
|
||||
/**
|
||||
* Is the API for selling products on Ebay.
|
||||
*/
|
||||
private EbaySeller ebaySeller;
|
||||
/**
|
||||
* Is the API for buying products on Amazon.
|
||||
*/
|
||||
private AmazonPurchaser amazonPurchaser;
|
||||
/**
|
||||
* Is the API for buying products on Ebay.
|
||||
*/
|
||||
private EbayPurchaser ebayPurchaser;
|
||||
|
||||
/**
|
||||
* Puts up the sell order.
|
||||
*
|
||||
* @param offer
|
||||
*/
|
||||
private void toSeller(final Offer offer) throws IllegalArgumentException {
|
||||
switch (offer.getTargetProduct().getDataOrigin()) {
|
||||
case EBAY -> this.ebaySeller.sellProduct(
|
||||
ProductMapper.mapProductToDTO(offer.getTargetProduct()));
|
||||
case AMAZON -> this.amazonSeller.sellProduct(
|
||||
ProductMapper.mapProductToDTO(offer.getTargetProduct()));
|
||||
default -> throw new IllegalArgumentException("Unsupported source plattform");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts up the buy order.
|
||||
*
|
||||
* @param offer
|
||||
*/
|
||||
private void toBuyer(final Offer offer) throws IllegalArgumentException {
|
||||
switch (offer.getSourceProduct().getDataOrigin()) {
|
||||
case EBAY -> ebayPurchaser.purchaseProduct(
|
||||
ProductMapper.mapProductToDTO(offer.getSourceProduct()));
|
||||
case AMAZON -> amazonPurchaser.purchaseProduct(
|
||||
ProductMapper.mapProductToDTO(offer.getSourceProduct()));
|
||||
default -> throw new IllegalArgumentException("Unsupported target plattform");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the class for placing orders on a target platform.
|
||||
*
|
||||
* @param db Persistence Interface
|
||||
* @param newSellerFactory Seller Factory
|
||||
* @param newPurchaserFactory Purchaser Factory
|
||||
*/
|
||||
public OfferProvisioner(
|
||||
final OfferPersistenceInterface db,
|
||||
final SellerFactory newSellerFactory,
|
||||
final PurchaserFactory newPurchaserFactory) {
|
||||
this.offerWriter = new OfferWriter(db);
|
||||
this.ebaySeller = newSellerFactory.createEbaySeller();
|
||||
this.amazonSeller = newSellerFactory.createAmazonSeller();
|
||||
this.ebayPurchaser = newPurchaserFactory.createEbayPurchaser();
|
||||
this.amazonPurchaser = newPurchaserFactory.createAmazonPurchaser();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method for placing orders on a target platform.
|
||||
*
|
||||
* @param offersToProvision
|
||||
*/
|
||||
public final void runProvisioner(final List<Offer> offersToProvision) {
|
||||
for (Offer newOffer : offersToProvision) {
|
||||
String newOfferId = FormattingUtil.removeSpaces(
|
||||
newOffer.getSourceProduct().getDataOrigin().toString()
|
||||
+ newOffer.getTargetProduct().getDataOrigin().toString()
|
||||
+ "_"
|
||||
+ newOffer.getSourceProduct().getProductId()
|
||||
+ newOffer.getTargetProduct().getProductId());
|
||||
|
||||
this.toSeller(newOffer);
|
||||
this.toBuyer(newOffer);
|
||||
newOffer.setOfferId(newOfferId);
|
||||
offerWriter.writeOfferToPersistence(newOffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package de.rwu.easydrop.service.processing;
|
||||
|
||||
import de.rwu.easydrop.api.dto.TransactionDTO;
|
||||
import de.rwu.easydrop.data.connector.TransactionPersistenceInterface;
|
||||
import de.rwu.easydrop.model.Offer;
|
||||
import de.rwu.easydrop.model.Transaction;
|
||||
import de.rwu.easydrop.service.mapping.TransactionMapper;
|
||||
import de.rwu.easydrop.util.Timestamp;
|
||||
|
||||
/**
|
||||
* Handles transactions.
|
||||
*
|
||||
* @since 0.3.0
|
||||
*/
|
||||
public class TransactionHandler {
|
||||
/**
|
||||
* Transaction persistence.
|
||||
*/
|
||||
private TransactionPersistenceInterface txPersistence;
|
||||
|
||||
/**
|
||||
* Creates new transaction handler.
|
||||
*
|
||||
* @param txdb transaction persistence
|
||||
*/
|
||||
public TransactionHandler(final TransactionPersistenceInterface txdb) {
|
||||
this.txPersistence = txdb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates transaction from offer.
|
||||
*
|
||||
* @param offer Offer
|
||||
*/
|
||||
public void turnOfferToTransaction(final Offer offer) {
|
||||
Transaction tx = new Transaction();
|
||||
tx.setOfferId(offer.getOfferId());
|
||||
tx.setVolume(offer.getTargetProduct().getCurrentPrice());
|
||||
tx.setEarnings(offer.getTargetProduct().getCurrentPrice()
|
||||
- offer.getSourceProduct().getCurrentPrice());
|
||||
tx.setTransactionTime(Timestamp.now());
|
||||
|
||||
// Write transaction to persistence
|
||||
TransactionDTO txDTO = TransactionMapper.mapTXToDTO(tx);
|
||||
txPersistence.writeTX(txDTO);
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,9 @@ import java.util.List;
|
||||
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import de.rwu.easydrop.exception.InvalidProductException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import de.rwu.easydrop.model.Product;
|
||||
import de.rwu.easydrop.model.ProductCatalogue;
|
||||
import de.rwu.easydrop.util.ProductsConfig;
|
||||
@@ -18,6 +20,11 @@ import lombok.Data;
|
||||
*/
|
||||
@Data
|
||||
public class CatalogueRetriever {
|
||||
/**
|
||||
* Logging instance.
|
||||
*/
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(CatalogueRetriever.class);
|
||||
|
||||
/**
|
||||
* User-configured products.
|
||||
*/
|
||||
@@ -57,22 +64,16 @@ public class CatalogueRetriever {
|
||||
pCat.getProductName(), pCat.getDescription());
|
||||
|
||||
for (Product product : pCat.getProducts()) {
|
||||
Product newProduct = new Product();
|
||||
newProduct.setDataOrigin(product.getDataOrigin());
|
||||
newProduct.setProductId(product.getProductId());
|
||||
|
||||
if (newProduct.getDataOrigin().equals("Amazon")) {
|
||||
newProduct = productRetriever.getProductFromAmazon(product.getProductId());
|
||||
} else if (newProduct.getDataOrigin().equals("eBay")) {
|
||||
newProduct = productRetriever.getProductFromEbay(product.getProductId());
|
||||
} else {
|
||||
throw new InvalidProductException("Product data origin is invalid");
|
||||
}
|
||||
Product newProduct = productRetriever.getProductFromWebshop(product.getDataOrigin(),
|
||||
product.getProductId());
|
||||
|
||||
newProductCatalogue.addProduct(newProduct);
|
||||
}
|
||||
|
||||
productCatalogues.add(newProductCatalogue);
|
||||
String catString = String.format(
|
||||
"%nLoaded Catalogue: %n%s", newProductCatalogue.toString());
|
||||
LOGGER.info(catString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package de.rwu.easydrop.service.retriever;
|
||||
|
||||
import de.rwu.easydrop.api.dto.OfferDTO;
|
||||
import de.rwu.easydrop.data.connector.OfferPersistenceInterface;
|
||||
import de.rwu.easydrop.model.Offer;
|
||||
import de.rwu.easydrop.service.mapping.OfferMapper;
|
||||
|
||||
/**
|
||||
* Retrieves offer information from different sources.
|
||||
*
|
||||
* @since 0.3.0
|
||||
*/
|
||||
public class OfferRetriever {
|
||||
/**
|
||||
* Persistence interface.
|
||||
*/
|
||||
private OfferPersistenceInterface persistence;
|
||||
|
||||
/**
|
||||
* Creates an Offer Retriever.
|
||||
*
|
||||
* @param db Persistence Interface
|
||||
*/
|
||||
public OfferRetriever(final OfferPersistenceInterface db) {
|
||||
this.persistence = db;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves an offer from persistence.
|
||||
*
|
||||
* @param offerId
|
||||
* @return Offer from persistence
|
||||
*/
|
||||
public Offer getOfferFromPersistence(final String offerId) {
|
||||
OfferPersistenceInterface src = persistence;
|
||||
|
||||
OfferDTO dto = src.getOfferDTOById(offerId);
|
||||
return OfferMapper.mapOfferFromDTO(dto);
|
||||
}
|
||||
}
|
||||
@@ -4,8 +4,9 @@ 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.data.connector.AbstractProductPersistence;
|
||||
import de.rwu.easydrop.data.connector.ProductPersistenceInterface;
|
||||
import de.rwu.easydrop.model.Product;
|
||||
import de.rwu.easydrop.model.Webshop;
|
||||
import de.rwu.easydrop.service.mapping.ProductMapper;
|
||||
import de.rwu.easydrop.service.validation.ProductValidator;
|
||||
|
||||
@@ -19,19 +20,20 @@ public class ProductRetriever {
|
||||
* Data source factory.
|
||||
*/
|
||||
private DataSourceFactory dataSourceFactory;
|
||||
|
||||
/**
|
||||
* @param newDataSourceFactory the dataSourceFactory to set
|
||||
* Persistence interface.
|
||||
*/
|
||||
public void setDataSourceFactory(final DataSourceFactory newDataSourceFactory) {
|
||||
this.dataSourceFactory = newDataSourceFactory;
|
||||
}
|
||||
private ProductPersistenceInterface persistence;
|
||||
|
||||
/**
|
||||
* @param newDataSourceFactory
|
||||
* @param newPersistence
|
||||
*/
|
||||
public ProductRetriever(final DataSourceFactory newDataSourceFactory) {
|
||||
this.setDataSourceFactory(newDataSourceFactory);
|
||||
public ProductRetriever(
|
||||
final DataSourceFactory newDataSourceFactory,
|
||||
final ProductPersistenceInterface newPersistence) {
|
||||
this.dataSourceFactory = newDataSourceFactory;
|
||||
this.persistence = newPersistence;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -73,12 +75,27 @@ public class ProductRetriever {
|
||||
* @return Product from persistence
|
||||
*/
|
||||
public Product getProductFromPersistence(final String productId) {
|
||||
AbstractProductPersistence src = dataSourceFactory.createProductPersistenceDataSource();
|
||||
|
||||
ProductDTO dto = src.getProductDTOById(productId);
|
||||
ProductDTO dto = persistence.getProductDTOById(productId);
|
||||
Product product = ProductMapper.mapProductFromDTO(dto);
|
||||
ProductValidator.validate(product);
|
||||
|
||||
return product;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a product from an API by name of the API so that high-level
|
||||
* components do not need to be extended
|
||||
* with exact function call names if we extend the list of webshops.
|
||||
*
|
||||
* @param shop Data source name, e.g. Amazon
|
||||
* @param productIdentifier Product name, translated to the correct product ID
|
||||
* for the data source
|
||||
* @return Product from that data source or null if data source not available
|
||||
*/
|
||||
public Product getProductFromWebshop(final Webshop shop, final String productIdentifier) {
|
||||
return switch (shop) {
|
||||
case AMAZON -> getProductFromAmazon(productIdentifier);
|
||||
case EBAY -> getProductFromEbay(productIdentifier);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package de.rwu.easydrop.service.validation;
|
||||
|
||||
import de.rwu.easydrop.exception.InvalidOfferException;
|
||||
import de.rwu.easydrop.model.Offer;
|
||||
|
||||
/**
|
||||
* Confirms validity of Offer data.
|
||||
*
|
||||
* @since 0.2.0
|
||||
*/
|
||||
public final class OfferValidator {
|
||||
/**
|
||||
* Private constructor to prevent unwanted instantiation.
|
||||
*
|
||||
* @throws UnsupportedOperationException always
|
||||
*/
|
||||
private OfferValidator() throws UnsupportedOperationException {
|
||||
throw new UnsupportedOperationException("This is a validator class, don't instantiate it.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure an Offer does not contain invalid information.
|
||||
*
|
||||
* @param offer the Offer
|
||||
*/
|
||||
public static void validate(final Offer offer) {
|
||||
try {
|
||||
if (offer.getOfferId().equals("")) {
|
||||
throw new InvalidOfferException("Offer ID cannot be empty");
|
||||
}
|
||||
if (offer.getLastUpdate().equals("")) {
|
||||
throw new InvalidOfferException("LastUpdate cannot be empty");
|
||||
}
|
||||
} catch (NullPointerException e) {
|
||||
throw new InvalidOfferException("Required information is missing in the offer", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,5 @@
|
||||
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;
|
||||
|
||||
@@ -31,26 +28,8 @@ public final class ProductValidator {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package de.rwu.easydrop.service.validation;
|
||||
|
||||
import de.rwu.easydrop.exception.InvalidTransactionException;
|
||||
import de.rwu.easydrop.model.Transaction;
|
||||
|
||||
/**
|
||||
* Validates transactions.
|
||||
*
|
||||
* @since 0.3.0
|
||||
*/
|
||||
public final class TransactionValidator {
|
||||
/**
|
||||
* Private constructor to prevent unwanted instantiation.
|
||||
*
|
||||
* @throws UnsupportedOperationException always
|
||||
*/
|
||||
private TransactionValidator() throws UnsupportedOperationException {
|
||||
throw new UnsupportedOperationException("This is a validator class, don't instantiate it.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure a transaction does not contain invalid information.
|
||||
*
|
||||
* @param tx the Transaction
|
||||
*/
|
||||
public static void validate(final Transaction tx) {
|
||||
try {
|
||||
if (tx.getOfferId().equals("")) {
|
||||
throw new InvalidTransactionException("Offer ID cannot be empty");
|
||||
}
|
||||
if (tx.getEarnings() == 0) {
|
||||
throw new InvalidTransactionException("Earnings can't be zero");
|
||||
}
|
||||
if (tx.getVolume() == 0) {
|
||||
throw new InvalidTransactionException("Volume can't be zero");
|
||||
}
|
||||
} catch (NullPointerException e) {
|
||||
throw new InvalidTransactionException(
|
||||
"Required information is missing in the transaction", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package de.rwu.easydrop.service.writer;
|
||||
import java.util.List;
|
||||
|
||||
import de.rwu.easydrop.api.dto.ProductDTO;
|
||||
import de.rwu.easydrop.data.connector.AbstractProductPersistence;
|
||||
import de.rwu.easydrop.data.connector.ProductPersistenceInterface;
|
||||
import de.rwu.easydrop.model.Product;
|
||||
import de.rwu.easydrop.model.ProductCatalogue;
|
||||
import de.rwu.easydrop.service.mapping.ProductMapper;
|
||||
@@ -18,14 +18,14 @@ public final class CatalogueWriter {
|
||||
/**
|
||||
* Holds a persistence reference.
|
||||
*/
|
||||
private AbstractProductPersistence persistence;
|
||||
private ProductPersistenceInterface persistence;
|
||||
|
||||
/**
|
||||
* Creates new instance.
|
||||
*
|
||||
* @param newPersistence
|
||||
*/
|
||||
public CatalogueWriter(final AbstractProductPersistence newPersistence) {
|
||||
public CatalogueWriter(final ProductPersistenceInterface newPersistence) {
|
||||
persistence = newPersistence;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ public final class CatalogueWriter {
|
||||
ProductValidator.validate(product);
|
||||
ProductDTO dto = ProductMapper.mapProductToDTO(product);
|
||||
|
||||
persistence.saveProduct(dto);
|
||||
persistence.writeProduct(dto);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package de.rwu.easydrop.service.writer;
|
||||
|
||||
import de.rwu.easydrop.api.dto.OfferDTO;
|
||||
import de.rwu.easydrop.data.connector.OfferPersistenceInterface;
|
||||
import de.rwu.easydrop.model.Offer;
|
||||
import de.rwu.easydrop.service.mapping.OfferMapper;
|
||||
|
||||
public class OfferWriter {
|
||||
/**
|
||||
* Persistence.
|
||||
*/
|
||||
private OfferPersistenceInterface persistence;
|
||||
|
||||
/**
|
||||
* @param newPersistence the persistence to set
|
||||
*/
|
||||
public OfferWriter(final OfferPersistenceInterface newPersistence) {
|
||||
this.persistence = newPersistence;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates and saves product to persistence.
|
||||
*
|
||||
* @param offer
|
||||
*/
|
||||
public void writeOfferToPersistence(final Offer offer) {
|
||||
OfferDTO dto = OfferMapper.mapOfferToDTO(offer);
|
||||
|
||||
persistence.writeOffer(dto);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package de.rwu.easydrop.service.writer;
|
||||
|
||||
import de.rwu.easydrop.api.dto.ProductDTO;
|
||||
import de.rwu.easydrop.data.connector.AbstractProductPersistence;
|
||||
import de.rwu.easydrop.data.connector.ProductPersistenceInterface;
|
||||
import de.rwu.easydrop.model.Product;
|
||||
import de.rwu.easydrop.service.mapping.ProductMapper;
|
||||
import de.rwu.easydrop.service.validation.ProductValidator;
|
||||
@@ -15,12 +15,12 @@ public class ProductWriter {
|
||||
/**
|
||||
* Persistence.
|
||||
*/
|
||||
private AbstractProductPersistence persistence;
|
||||
private ProductPersistenceInterface persistence;
|
||||
|
||||
/**
|
||||
* @param newPersistence the persistence to set
|
||||
*/
|
||||
public void setPersistence(final AbstractProductPersistence newPersistence) {
|
||||
public ProductWriter(final ProductPersistenceInterface newPersistence) {
|
||||
this.persistence = newPersistence;
|
||||
}
|
||||
|
||||
@@ -33,6 +33,6 @@ public class ProductWriter {
|
||||
ProductValidator.validate(product);
|
||||
ProductDTO dto = ProductMapper.mapProductToDTO(product);
|
||||
|
||||
persistence.saveProduct(dto);
|
||||
persistence.writeProduct(dto);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package de.rwu.easydrop.service.writer;
|
||||
|
||||
import de.rwu.easydrop.api.dto.TransactionDTO;
|
||||
import de.rwu.easydrop.data.connector.TransactionPersistenceInterface;
|
||||
import de.rwu.easydrop.model.Transaction;
|
||||
import de.rwu.easydrop.service.mapping.TransactionMapper;
|
||||
import de.rwu.easydrop.service.validation.TransactionValidator;
|
||||
|
||||
public class TransactionWriter {
|
||||
/**
|
||||
* Persistence.
|
||||
*/
|
||||
private TransactionPersistenceInterface persistence;
|
||||
|
||||
/**
|
||||
* @param newPersistence the persistence to set
|
||||
*/
|
||||
public TransactionWriter(final TransactionPersistenceInterface newPersistence) {
|
||||
this.persistence = newPersistence;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates and saves a transaction to persistence.
|
||||
*
|
||||
* @param tx Transaction
|
||||
*/
|
||||
public void writeTXToPersistence(final Transaction tx) {
|
||||
TransactionDTO dto = TransactionMapper.mapTXToDTO(tx);
|
||||
TransactionValidator.validate(tx);
|
||||
|
||||
persistence.writeTX(dto);
|
||||
}
|
||||
}
|
||||
@@ -37,4 +37,14 @@ public final class FormattingUtil {
|
||||
public static String urlEncode(final String str) {
|
||||
return str.replace(" ", "+");
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes spaces from target string.
|
||||
*
|
||||
* @param str String
|
||||
* @return Space-less string
|
||||
*/
|
||||
public static String removeSpaces(final String str) {
|
||||
return str.replace(" ", "");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import com.jayway.jsonpath.JsonPathException;
|
||||
|
||||
import de.rwu.easydrop.model.Product;
|
||||
import de.rwu.easydrop.model.ProductCatalogue;
|
||||
import de.rwu.easydrop.model.Webshop;
|
||||
|
||||
/**
|
||||
* Reads the user-specified catalogue of products.
|
||||
@@ -122,8 +123,8 @@ public final class ProductsConfig {
|
||||
ArrayList<HashMap<String, Object>> identifiers = JsonPath.read(jsonIdentifiers, "$");
|
||||
|
||||
for (HashMap<String, Object> product : identifiers) {
|
||||
String dataOrigin = product.keySet().iterator().next();
|
||||
String identifier = product.get(dataOrigin).toString();
|
||||
Webshop dataOrigin = Webshop.fromString(product.keySet().iterator().next());
|
||||
String identifier = product.get(dataOrigin.toString()).toString();
|
||||
|
||||
Product newProduct = new Product();
|
||||
newProduct.setDataOrigin(dataOrigin);
|
||||
|
||||
29
src/main/java/de/rwu/easydrop/util/Timestamp.java
Normal file
29
src/main/java/de/rwu/easydrop/util/Timestamp.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package de.rwu.easydrop.util;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
/**
|
||||
* Serves as a timestamp source.
|
||||
*
|
||||
* @since 0.3.0
|
||||
*/
|
||||
public final class Timestamp {
|
||||
/**
|
||||
* Hidden constructor.
|
||||
*/
|
||||
private Timestamp() {
|
||||
// Don't instantiate me!
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a formatted time string.
|
||||
*
|
||||
* @return String such as "2023-01-01 00:00:00"
|
||||
*/
|
||||
public static String now() {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
return now.format(formatter);
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import org.mockito.MockitoAnnotations;
|
||||
|
||||
import de.rwu.easydrop.api.dto.ProductDTO;
|
||||
import de.rwu.easydrop.exception.DataWriterException;
|
||||
import de.rwu.easydrop.model.Webshop;
|
||||
|
||||
class AbstractDataWriterTest {
|
||||
private static String demoProductId = "whateverId";
|
||||
@@ -42,8 +43,8 @@ class AbstractDataWriterTest {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDataTarget() {
|
||||
return "Test";
|
||||
protected Webshop getDataTarget() {
|
||||
return Webshop.AMAZON;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -53,21 +54,10 @@ class AbstractDataWriterTest {
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
void sendPutRequest_wrongDataSource_throwsException() {
|
||||
ProductDTO dto = new ProductDTO(demoProductId, "Amazon");
|
||||
|
||||
DataWriterException e = assertThrows(DataWriterException.class, () -> {
|
||||
writer.sendPutRequest(dto, "testApiType");
|
||||
});
|
||||
|
||||
assertEquals("Product data source and target testApiType API are incompatible.", e.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void sendPutRequest_badResponseCode_throwsException() throws IOException {
|
||||
// Set up DTO
|
||||
ProductDTO dto = new ProductDTO(demoProductId, "Test");
|
||||
ProductDTO dto = new ProductDTO(demoProductId, Webshop.AMAZON);
|
||||
|
||||
// Set up Mocks
|
||||
AbstractDataWriter mockWriter = mock(AbstractDataWriter.class);
|
||||
@@ -79,13 +69,13 @@ class AbstractDataWriterTest {
|
||||
writer.sendPutRequest(dto, "Sales");
|
||||
});
|
||||
|
||||
assertEquals("Test Sales API responded with error code 400", e.getMessage());
|
||||
assertEquals("AMAZON Sales API responded with error code 400", e.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void sendPutRequest_ioException_throwsException() throws IOException {
|
||||
// Set up DTO
|
||||
ProductDTO dto = new ProductDTO(demoProductId, "Test");
|
||||
ProductDTO dto = new ProductDTO(demoProductId, Webshop.AMAZON);
|
||||
|
||||
// Set up Mocks
|
||||
AbstractDataWriter mockWriter = mock(AbstractDataWriter.class);
|
||||
@@ -96,13 +86,13 @@ class AbstractDataWriterTest {
|
||||
writer.sendPutRequest(dto, "testApiType");
|
||||
});
|
||||
|
||||
assertEquals("Couldn't fulfill Test API request", e.getMessage());
|
||||
assertEquals("Couldn't fulfill AMAZON API request", e.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void sendPutRequest_successfulRequest() throws IOException {
|
||||
// Set up DTO
|
||||
ProductDTO dto = new ProductDTO(demoProductId, "test");
|
||||
ProductDTO dto = new ProductDTO(demoProductId, Webshop.AMAZON);
|
||||
|
||||
// Set up Mocks
|
||||
AbstractDataWriter mockWriter = mock(AbstractDataWriter.class);
|
||||
@@ -112,10 +102,21 @@ class AbstractDataWriterTest {
|
||||
HttpURLConnection mockConnection = mock(HttpURLConnection.class);
|
||||
when(mockURL.openConnection()).thenReturn(mockConnection);
|
||||
when(mockConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_OK);
|
||||
when(mockWriter.getDataTarget()).thenReturn("test");
|
||||
when(mockWriter.getDataTarget()).thenReturn(Webshop.AMAZON);
|
||||
|
||||
assertDoesNotThrow(() -> {
|
||||
mockWriter.sendPutRequest(dto, "Purchase");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void sendPutRequest_wrongDataTarget() {
|
||||
ProductDTO dto = new ProductDTO(demoProductId, Webshop.EBAY);
|
||||
|
||||
DataWriterException e = assertThrows(DataWriterException.class, () -> {
|
||||
writer.sendPutRequest(dto, demoProductId);
|
||||
});
|
||||
|
||||
assertEquals("Product data source and target whateverId API are incompatible.", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import java.net.URL;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import de.rwu.easydrop.api.dto.ProductDTO;
|
||||
import de.rwu.easydrop.model.Webshop;
|
||||
|
||||
class AbstractPurchaserTest {
|
||||
private AbstractPurchaser mockPurchaser = mock(AbstractPurchaser.class);
|
||||
@@ -20,7 +21,7 @@ class AbstractPurchaserTest {
|
||||
@Test
|
||||
void purchaseProduct_CorrectApiTypeInException() throws IOException {
|
||||
// Set up DTO
|
||||
ProductDTO dto = new ProductDTO("12345", "test");
|
||||
ProductDTO dto = new ProductDTO("12345", Webshop.AMAZON);
|
||||
|
||||
// Set up mocks
|
||||
URL mockURL = mock(URL.class);
|
||||
@@ -29,7 +30,7 @@ class AbstractPurchaserTest {
|
||||
HttpURLConnection mockConnection = mock(HttpURLConnection.class);
|
||||
when(mockURL.openConnection()).thenReturn(mockConnection);
|
||||
when(mockConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_OK);
|
||||
when(mockPurchaser.getDataTarget()).thenReturn("test");
|
||||
when(mockPurchaser.getDataTarget()).thenReturn(Webshop.AMAZON);
|
||||
|
||||
assertDoesNotThrow(() -> {
|
||||
mockPurchaser.purchaseProduct(dto);
|
||||
|
||||
@@ -13,6 +13,7 @@ import java.net.URL;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import de.rwu.easydrop.api.dto.ProductDTO;
|
||||
import de.rwu.easydrop.model.Webshop;
|
||||
|
||||
class AbstractSellerTest {
|
||||
private AbstractSeller mockSeller = mock(AbstractSeller.class);
|
||||
@@ -20,7 +21,7 @@ class AbstractSellerTest {
|
||||
@Test
|
||||
void purchaseProduct_CorrectApiTypeInException() throws IOException {
|
||||
// Set up DTO
|
||||
ProductDTO dto = new ProductDTO("12345", "test");
|
||||
ProductDTO dto = new ProductDTO("12345", Webshop.AMAZON);
|
||||
|
||||
// Set up mocks
|
||||
URL mockURL = mock(URL.class);
|
||||
@@ -29,7 +30,7 @@ class AbstractSellerTest {
|
||||
HttpURLConnection mockConnection = mock(HttpURLConnection.class);
|
||||
when(mockURL.openConnection()).thenReturn(mockConnection);
|
||||
when(mockConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_OK);
|
||||
when(mockSeller.getDataTarget()).thenReturn("test");
|
||||
when(mockSeller.getDataTarget()).thenReturn(Webshop.AMAZON);
|
||||
|
||||
assertDoesNotThrow(() -> {
|
||||
mockSeller.sellProduct(dto);
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.mockito.MockitoAnnotations;
|
||||
|
||||
import de.rwu.easydrop.api.dto.ProductDTO;
|
||||
import de.rwu.easydrop.exception.DataSourceException;
|
||||
import de.rwu.easydrop.model.Webshop;
|
||||
|
||||
class AmazonProductDataSourceTest {
|
||||
|
||||
@@ -28,7 +29,7 @@ class AmazonProductDataSourceTest {
|
||||
|
||||
private static String demoApiKey = "my-api-key";
|
||||
private static String demoApiUrl = "https://www.example.com/api";
|
||||
private static String demoDataOrigin = "Amazon";
|
||||
private static Webshop demoDataOrigin = Webshop.AMAZON;
|
||||
private static String demoProductId = "whateverId";
|
||||
|
||||
@BeforeEach
|
||||
@@ -138,7 +139,7 @@ class AmazonProductDataSourceTest {
|
||||
|
||||
// Verify the product DTO properties
|
||||
assertEquals(demoProductId, result.getProductId());
|
||||
assertEquals("Amazon", result.getDataOrigin());
|
||||
assertEquals(Webshop.AMAZON, result.getDataOrigin());
|
||||
assertEquals(true, result.isAvailable());
|
||||
assertEquals(10.0, result.getCurrentPrice());
|
||||
assertEquals(2.5, result.getDeliveryPrice());
|
||||
@@ -149,33 +150,60 @@ class AmazonProductDataSourceTest {
|
||||
void testGetProductDTOById_failedRequest() throws IOException {
|
||||
// Set up the test environment
|
||||
|
||||
AmazonProductDataSource dataSource = mock(AmazonProductDataSource.class);
|
||||
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.getDataOrigin()).thenReturn(demoDataOrigin);
|
||||
when(DataSource.createApiUrl(demoProductId)).thenReturn(mockURL);
|
||||
when(DataSource.getProductDTOById(demoProductId)).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(demoProductId);
|
||||
DataSource.getProductDTOById(demoProductId);
|
||||
});
|
||||
|
||||
// Verify the exception message
|
||||
assertEquals("Nothing found: Amazon API responded with error code 404", exception.getMessage());
|
||||
assertEquals("Nothing found: AMAZON API responded with error code 404", exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetProductDTOById_emptyResponse() throws IOException {
|
||||
// Set up the test environment
|
||||
String mockResponse = "";
|
||||
|
||||
AmazonProductDataSource dataSource = mock(AmazonProductDataSource.class);
|
||||
URL mockURL = mock(URL.class);
|
||||
when(dataSource.createApiUrl(demoProductId)).thenReturn(mockURL);
|
||||
when(dataSource.buildProductDTO(any(), anyString())).thenCallRealMethod();
|
||||
HttpURLConnection mockConnection = mock(HttpURLConnection.class);
|
||||
when(mockURL.openConnection()).thenReturn(mockConnection);
|
||||
when(mockConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_OK);
|
||||
when(mockConnection.getInputStream()).thenReturn(new ByteArrayInputStream(mockResponse.getBytes()));
|
||||
when(dataSource.getProductDTOById(demoProductId)).thenCallRealMethod();
|
||||
|
||||
// Invoke the method
|
||||
ProductDTO result = dataSource.getProductDTOById(demoProductId);
|
||||
|
||||
// Verify the product DTO properties
|
||||
assertEquals(demoProductId, result.getProductId());
|
||||
assertEquals(Webshop.AMAZON, result.getDataOrigin());
|
||||
assertEquals(false, result.isAvailable());
|
||||
assertEquals(0.0, result.getCurrentPrice());
|
||||
assertEquals(0.0, result.getDeliveryPrice());
|
||||
assertEquals(null, result.getMerchant());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetProductDTOById_ioException() throws IOException {
|
||||
// Set up the test environment
|
||||
AmazonProductDataSource dataSource = mock(AmazonProductDataSource.class);
|
||||
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();
|
||||
when(DataSource.getDataOrigin()).thenReturn(demoDataOrigin);
|
||||
when(DataSource.createApiUrl(demoProductId)).thenReturn(mockURL);
|
||||
when(DataSource.getProductDTOById(demoProductId)).thenCallRealMethod();
|
||||
when(DataSource.buildProductDTO(any(), anyString())).thenCallRealMethod();
|
||||
HttpURLConnection mockConnection = mock(HttpURLConnection.class);
|
||||
when(mockURL.openConnection()).thenReturn(mockConnection);
|
||||
when(mockConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_OK);
|
||||
@@ -183,16 +211,16 @@ class AmazonProductDataSourceTest {
|
||||
|
||||
// Invoke the method and verify the exception
|
||||
DataSourceException exception = assertThrows(DataSourceException.class, () -> {
|
||||
dataSource.getProductDTOById(demoProductId);
|
||||
DataSource.getProductDTOById(demoProductId);
|
||||
});
|
||||
|
||||
// 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();
|
||||
Webshop dataOrigin = demoDataSource.getDataOrigin();
|
||||
assertEquals(demoDataOrigin, dataOrigin);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package de.rwu.easydrop.api.client;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.MalformedURLException;
|
||||
@@ -12,15 +11,14 @@ 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.DataWriterException;
|
||||
import de.rwu.easydrop.model.Webshop;
|
||||
|
||||
class AmazonPurchaserTest {
|
||||
private AmazonPurchaser demoPurchaser;
|
||||
|
||||
private static String demoApiKey = "my-api-key";
|
||||
private static String demoApiUrl = "https://www.example.com/api";
|
||||
private static String demoDataTarget = "Amazon";
|
||||
private static Webshop demoDataTarget = Webshop.AMAZON;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
@@ -72,7 +70,7 @@ class AmazonPurchaserTest {
|
||||
|
||||
@Test
|
||||
void getDataTarget_ReturnsExpectedDataOrigin() {
|
||||
String dataTarget = demoPurchaser.getDataTarget();
|
||||
Webshop dataTarget = demoPurchaser.getDataTarget();
|
||||
assertEquals(demoDataTarget, dataTarget);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,12 +11,14 @@ import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import de.rwu.easydrop.model.Webshop;
|
||||
|
||||
class AmazonSellerTest {
|
||||
private AmazonSeller demoSeller;
|
||||
|
||||
private static String demoApiKey = "my-api-key";
|
||||
private static String demoApiUrl = "https://www.example.com/api";
|
||||
private static String demoDataTarget = "Amazon";
|
||||
private static Webshop demoDataTarget = Webshop.AMAZON;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
@@ -68,7 +70,7 @@ class AmazonSellerTest {
|
||||
|
||||
@Test
|
||||
void getDataTarget_ReturnsExpectedDataOrigin() {
|
||||
String dataTarget = demoSeller.getDataTarget();
|
||||
Webshop dataTarget = demoSeller.getDataTarget();
|
||||
assertEquals(demoDataTarget, dataTarget);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package de.rwu.easydrop.api.client;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import javax.naming.ConfigurationException;
|
||||
@@ -11,17 +9,14 @@ import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.sqlite.SQLiteDataSource;
|
||||
|
||||
import de.rwu.easydrop.data.connector.SQLiteConnector;
|
||||
import de.rwu.easydrop.exception.PersistenceException;
|
||||
import de.rwu.easydrop.util.Config;
|
||||
|
||||
class DataSourceFactoryTest {
|
||||
@Mock
|
||||
private Config config;
|
||||
|
||||
private DataSourceFactory dataSourceFactory;
|
||||
private DataSourceFactory DataSourceFactory;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() throws ConfigurationException {
|
||||
@@ -30,40 +25,24 @@ class DataSourceFactoryTest {
|
||||
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);
|
||||
DataSourceFactory = new DataSourceFactory(config);
|
||||
}
|
||||
|
||||
@Test
|
||||
void createAmazonProductDataSource_ReturnsAmazonProductDataSource() {
|
||||
// Act
|
||||
AmazonProductDataSource dataSource = dataSourceFactory.createAmazonProductDataSource();
|
||||
AmazonProductDataSource DataSource = DataSourceFactory.createAmazonProductDataSource();
|
||||
|
||||
// Assert
|
||||
assertEquals("amazon-api-key", dataSource.getApiKey());
|
||||
assertEquals("amazon-api-key", DataSource.getApiKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
void createEbayItemDataSource_ReturnsEbayItemDataSource() {
|
||||
// Act
|
||||
EbayItemDataSource dataSource = dataSourceFactory.createEbayItemDataSource();
|
||||
EbayItemDataSource DataSource = DataSourceFactory.createEbayItemDataSource();
|
||||
|
||||
// Assert
|
||||
assertEquals("ebay-api-key", dataSource.getApiKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
void createProductPersistenceDataSource_NullPersistence() {
|
||||
PersistenceException exception = assertThrows(PersistenceException.class, () -> {
|
||||
dataSourceFactory.createProductPersistenceDataSource();
|
||||
});
|
||||
|
||||
assertEquals("Persistence is not set", exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void createProductPersistenceDataSource_WorkingPersistence() {
|
||||
dataSourceFactory.setPersistence(new SQLiteConnector(new SQLiteDataSource()));
|
||||
|
||||
assertDoesNotThrow(() -> dataSourceFactory.createProductPersistenceDataSource());
|
||||
assertEquals("ebay-api-key", DataSource.getApiKey());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,13 +19,14 @@ import org.mockito.MockitoAnnotations;
|
||||
|
||||
import de.rwu.easydrop.api.dto.ProductDTO;
|
||||
import de.rwu.easydrop.exception.DataSourceException;
|
||||
import de.rwu.easydrop.model.Webshop;
|
||||
|
||||
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 Webshop demoDataOrigin = Webshop.EBAY;
|
||||
private static String demoQuery = "iPhone";
|
||||
|
||||
@BeforeEach
|
||||
@@ -82,7 +83,7 @@ class EbayItemDataSourceTest {
|
||||
|
||||
ProductDTO result = demoDataSource.buildProductDTO(product, json);
|
||||
|
||||
assertEquals("eBay", result.getDataOrigin());
|
||||
assertEquals(Webshop.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
|
||||
@@ -91,7 +92,7 @@ class EbayItemDataSourceTest {
|
||||
|
||||
@Test
|
||||
void getDataOrigin_ReturnsExpectedDataOrigin() {
|
||||
String dataOrigin = demoDataSource.getDataOrigin();
|
||||
Webshop dataOrigin = demoDataSource.getDataOrigin();
|
||||
assertEquals(demoDataOrigin, dataOrigin);
|
||||
}
|
||||
|
||||
@@ -105,21 +106,21 @@ class EbayItemDataSourceTest {
|
||||
void testGetProductDTOById_failedRequest() throws IOException {
|
||||
// Set up the test environment
|
||||
|
||||
EbayItemDataSource dataSource = mock(EbayItemDataSource.class);
|
||||
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();
|
||||
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);
|
||||
DataSource.getProductDTOById(demoQuery);
|
||||
});
|
||||
|
||||
// Verify the exception message
|
||||
assertEquals("Nothing found: eBay API responded with error code 404", exception.getMessage());
|
||||
assertEquals("Nothing found: EBAY API responded with error code 404", exception.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,12 +11,14 @@ import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import de.rwu.easydrop.model.Webshop;
|
||||
|
||||
class EbayPurchaserTest {
|
||||
private EbayPurchaser demoPurchaser;
|
||||
|
||||
private static String demoApiKey = "my-api-key";
|
||||
private static String demoApiUrl = "https://www.example.com/api";
|
||||
private static String demoDataTarget = "eBay";
|
||||
private static Webshop demoDataTarget = Webshop.EBAY;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
@@ -65,7 +67,7 @@ class EbayPurchaserTest {
|
||||
|
||||
@Test
|
||||
void getDataTarget_ReturnsExpectedDataOrigin() {
|
||||
String dataTarget = demoPurchaser.getDataTarget();
|
||||
Webshop dataTarget = demoPurchaser.getDataTarget();
|
||||
assertEquals(demoDataTarget, dataTarget);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,12 +11,14 @@ import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import de.rwu.easydrop.model.Webshop;
|
||||
|
||||
class EbaySellerTest {
|
||||
private EbaySeller demoSeller;
|
||||
|
||||
private static String demoApiKey = "my-api-key";
|
||||
private static String demoApiUrl = "https://www.example.com/api";
|
||||
private static String demoDataTarget = "eBay";
|
||||
private static Webshop demoDataTarget = Webshop.EBAY;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
@@ -65,7 +67,7 @@ class EbaySellerTest {
|
||||
|
||||
@Test
|
||||
void getDataTarget_ReturnsExpectedDataOrigin() {
|
||||
String dataTarget = demoSeller.getDataTarget();
|
||||
Webshop dataTarget = demoSeller.getDataTarget();
|
||||
assertEquals(demoDataTarget, dataTarget);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
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.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 PurchaserFactoryTest {
|
||||
|
||||
@Mock
|
||||
private Config mockConfig;
|
||||
|
||||
private PurchaserFactory purchaserFactory;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() throws ConfigurationException {
|
||||
MockitoAnnotations.openMocks(this);
|
||||
purchaserFactory = new PurchaserFactory(mockConfig);
|
||||
purchaserFactory.setConfig(mockConfig);
|
||||
}
|
||||
|
||||
@Test
|
||||
void createAmazonPurchaser_ValidConfig_ReturnsAmazonPurchaser() {
|
||||
// Arrange
|
||||
String amazonApiUrl = "amazon_api_url";
|
||||
String amazonApiKey = "amazon_api_key";
|
||||
|
||||
when(mockConfig.getProperty("AMAZON_API_URL")).thenReturn(amazonApiUrl);
|
||||
when(mockConfig.getProperty("AMAZON_API_KEY")).thenReturn(amazonApiKey);
|
||||
|
||||
// Act
|
||||
AmazonPurchaser amazonPurchaser = purchaserFactory.createAmazonPurchaser();
|
||||
|
||||
// Assert
|
||||
assertNotNull(amazonPurchaser);
|
||||
assertEquals(amazonApiKey, amazonPurchaser.getApiKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
void createEbayPurchaser_ValidConfig_ReturnsEbayPurchaser() {
|
||||
// Arrange
|
||||
String ebayApiUrl = "ebay_api_url";
|
||||
String ebayApiKey = "ebay_api_key";
|
||||
|
||||
when(mockConfig.getProperty("EBAY_API_URL")).thenReturn(ebayApiUrl);
|
||||
when(mockConfig.getProperty("EBAY_API_KEY")).thenReturn(ebayApiKey);
|
||||
|
||||
// Act
|
||||
EbayPurchaser ebayPurchaser = purchaserFactory.createEbayPurchaser();
|
||||
|
||||
// Assert
|
||||
assertNotNull(ebayPurchaser);
|
||||
assertEquals(ebayApiKey, ebayPurchaser.getApiKey());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
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.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 SellerFactoryTest {
|
||||
|
||||
@Mock
|
||||
private Config mockConfig;
|
||||
|
||||
private SellerFactory sellerFactory;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() throws ConfigurationException {
|
||||
MockitoAnnotations.openMocks(this);
|
||||
sellerFactory = new SellerFactory(mockConfig);
|
||||
sellerFactory.setConfig(mockConfig);
|
||||
}
|
||||
|
||||
@Test
|
||||
void createAmazonSeller_ValidConfig_ReturnsAmazonSeller() {
|
||||
// Arrange
|
||||
String amazonApiUrl = "amazon_api_url";
|
||||
String amazonApiKey = "amazon_api_key";
|
||||
|
||||
when(mockConfig.getProperty("AMAZON_API_URL")).thenReturn(amazonApiUrl);
|
||||
when(mockConfig.getProperty("AMAZON_API_KEY")).thenReturn(amazonApiKey);
|
||||
|
||||
// Act
|
||||
AmazonSeller amazonSeller = sellerFactory.createAmazonSeller();
|
||||
|
||||
// Assert
|
||||
assertNotNull(amazonSeller);
|
||||
assertEquals(amazonApiKey, amazonSeller.getApiKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
void createEbaySeller_ValidConfig_ReturnsEbaySeller() {
|
||||
// Arrange
|
||||
String ebayApiUrl = "ebay_api_url";
|
||||
String ebayApiKey = "ebay_api_key";
|
||||
|
||||
when(mockConfig.getProperty("EBAY_API_URL")).thenReturn(ebayApiUrl);
|
||||
when(mockConfig.getProperty("EBAY_API_KEY")).thenReturn(ebayApiKey);
|
||||
|
||||
// Act
|
||||
EbaySeller ebaySeller = sellerFactory.createEbaySeller();
|
||||
|
||||
// Assert
|
||||
assertNotNull(ebaySeller);
|
||||
assertEquals(ebayApiKey, ebaySeller.getApiKey());
|
||||
}
|
||||
}
|
||||
@@ -6,13 +6,15 @@ import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import de.rwu.easydrop.model.Webshop;
|
||||
|
||||
class ProductDTOTest {
|
||||
|
||||
@Test
|
||||
void constructor_SetsProductIdAndDataOrigin() {
|
||||
// Arrange
|
||||
String productId = "12345";
|
||||
String dataOrigin = "Amazon";
|
||||
Webshop dataOrigin = Webshop.AMAZON;
|
||||
|
||||
// Act
|
||||
ProductDTO productDTO = new ProductDTO(productId, dataOrigin);
|
||||
@@ -25,19 +27,19 @@ class ProductDTOTest {
|
||||
@Test
|
||||
void gettersAndSetters_WorkAsExpected() {
|
||||
// Arrange
|
||||
ProductDTO productDTO = new ProductDTO("12345", "Amazon");
|
||||
ProductDTO productDTO = new ProductDTO("12345", Webshop.AMAZON);
|
||||
|
||||
// Act and Assert
|
||||
assertEquals("12345", productDTO.getProductId());
|
||||
assertEquals("Amazon", productDTO.getDataOrigin());
|
||||
assertEquals(Webshop.AMAZON, productDTO.getDataOrigin());
|
||||
|
||||
// Modify fields
|
||||
productDTO.setProductId("54321");
|
||||
productDTO.setDataOrigin("eBay");
|
||||
productDTO.setDataOrigin(Webshop.EBAY);
|
||||
|
||||
// Assert
|
||||
assertEquals("54321", productDTO.getProductId());
|
||||
assertEquals("eBay", productDTO.getDataOrigin());
|
||||
assertEquals(Webshop.EBAY, productDTO.getDataOrigin());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -8,45 +8,51 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
import org.junit.jupiter.api.TestInstance.Lifecycle;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.sqlite.SQLiteDataSource;
|
||||
|
||||
import de.rwu.easydrop.api.dto.OfferDTO;
|
||||
import de.rwu.easydrop.api.dto.ProductDTO;
|
||||
import de.rwu.easydrop.api.dto.TransactionDTO;
|
||||
import de.rwu.easydrop.exception.PersistenceException;
|
||||
import de.rwu.easydrop.model.Webshop;
|
||||
|
||||
@TestInstance(Lifecycle.PER_CLASS)
|
||||
class SQLiteConnectorTest {
|
||||
private static final String TEST_PRODUCT_ID = "12345";
|
||||
private SQLiteConnector sqliteConnector;
|
||||
private SQLiteConnector sqliteConnector = new SQLiteConnector(new SQLiteDataSource());
|
||||
@Mock
|
||||
private Connection connection;
|
||||
|
||||
@Mock
|
||||
private PreparedStatement statement;
|
||||
|
||||
@Mock
|
||||
private ResultSet resultSet;
|
||||
|
||||
@Mock
|
||||
private SQLiteDataSource mockDataSource;
|
||||
|
||||
@BeforeAll
|
||||
public void setup() {
|
||||
sqliteConnector = new SQLiteConnector(new SQLiteDataSource());
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void clearDatabase() {
|
||||
public void prepare() {
|
||||
MockitoAnnotations.openMocks(this);
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveProduct_ValidProduct_SuccessfullySaved() {
|
||||
void writeProduct_ValidProduct_SuccessfullySaved() {
|
||||
// Arrange
|
||||
sqliteConnector.clearData();
|
||||
ProductDTO ProductDTO = new ProductDTO(TEST_PRODUCT_ID, "Amazon");
|
||||
ProductDTO.setDataOrigin("Amazon");
|
||||
ProductDTO ProductDTO = new ProductDTO(TEST_PRODUCT_ID, Webshop.AMAZON);
|
||||
ProductDTO.setDataOrigin(Webshop.AMAZON);
|
||||
ProductDTO.setProductId(TEST_PRODUCT_ID);
|
||||
ProductDTO.setCurrentPrice(9.99);
|
||||
ProductDTO.setMerchant("Sample Merchant");
|
||||
@@ -54,12 +60,12 @@ class SQLiteConnectorTest {
|
||||
ProductDTO.setAvailable(true);
|
||||
|
||||
// Act
|
||||
assertDoesNotThrow(() -> sqliteConnector.saveProduct(ProductDTO));
|
||||
assertDoesNotThrow(() -> sqliteConnector.writeProduct(ProductDTO));
|
||||
|
||||
// Assert
|
||||
ProductDTO savedProductDTO = sqliteConnector.getProductDTOById(TEST_PRODUCT_ID);
|
||||
assertNotNull(savedProductDTO);
|
||||
assertEquals("Amazon", savedProductDTO.getDataOrigin());
|
||||
assertEquals(Webshop.AMAZON, savedProductDTO.getDataOrigin());
|
||||
assertEquals(TEST_PRODUCT_ID, savedProductDTO.getProductId());
|
||||
assertEquals(9.99, savedProductDTO.getCurrentPrice());
|
||||
assertEquals("Sample Merchant", savedProductDTO.getMerchant());
|
||||
@@ -78,7 +84,7 @@ class SQLiteConnectorTest {
|
||||
|
||||
// Assert
|
||||
assertNotNull(ProductDTO);
|
||||
assertEquals("Amazon", ProductDTO.getDataOrigin());
|
||||
assertEquals(Webshop.AMAZON, ProductDTO.getDataOrigin());
|
||||
assertEquals(TEST_PRODUCT_ID, ProductDTO.getProductId());
|
||||
assertEquals(9.99, ProductDTO.getCurrentPrice());
|
||||
assertEquals("Sample Merchant", ProductDTO.getMerchant());
|
||||
@@ -111,14 +117,14 @@ class SQLiteConnectorTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveProduct_ThrowsPersistenceException_OnSQLException() throws SQLException {
|
||||
void writeProduct_ThrowsPersistenceException_OnSQLException() throws SQLException {
|
||||
// Arrange
|
||||
ProductDTO ProductDTO = new ProductDTO(TEST_PRODUCT_ID, "Amazon");
|
||||
ProductDTO ProductDTO = new ProductDTO(TEST_PRODUCT_ID, Webshop.AMAZON);
|
||||
sqliteConnector.setDb(mockDataSource);
|
||||
doThrow(SQLException.class).when(mockDataSource).getConnection();
|
||||
|
||||
// Act and Assert
|
||||
assertThrows(PersistenceException.class, () -> sqliteConnector.saveProduct(ProductDTO));
|
||||
assertThrows(PersistenceException.class, () -> sqliteConnector.writeProduct(ProductDTO));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -143,53 +149,179 @@ class SQLiteConnectorTest {
|
||||
}
|
||||
|
||||
private void insertSampleProduct() {
|
||||
ProductDTO ProductDTO = new ProductDTO(TEST_PRODUCT_ID, "Amazon");
|
||||
ProductDTO.setCurrentPrice(9.99);
|
||||
ProductDTO.setMerchant("Sample Merchant");
|
||||
ProductDTO.setDeliveryPrice(2.50);
|
||||
ProductDTO.setAvailable(true);
|
||||
sqliteConnector.saveProduct(ProductDTO);
|
||||
ProductDTO productDTO = new ProductDTO(TEST_PRODUCT_ID, Webshop.AMAZON);
|
||||
productDTO.setCurrentPrice(9.99);
|
||||
productDTO.setMerchant("Sample Merchant");
|
||||
productDTO.setDeliveryPrice(2.50);
|
||||
productDTO.setAvailable(true);
|
||||
sqliteConnector.writeProduct(productDTO);
|
||||
}
|
||||
|
||||
private void insertSampleOffer() {
|
||||
ProductDTO p1 = new ProductDTO("p1", Webshop.AMAZON);
|
||||
p1.setCurrentPrice(123f);
|
||||
|
||||
ProductDTO p2 = new ProductDTO("p2", Webshop.EBAY);
|
||||
p2.setCurrentPrice(234f);
|
||||
|
||||
OfferDTO dto = new OfferDTO();
|
||||
dto.setOfferId("123");
|
||||
dto.setLastUpdate("2020-01-01 00:00:00");
|
||||
dto.setSourceProduct(p1);
|
||||
dto.setTargetProduct(p2);
|
||||
sqliteConnector.writeOffer(dto);
|
||||
}
|
||||
|
||||
private void insertSampleTransaction() {
|
||||
TransactionDTO dto = new TransactionDTO();
|
||||
dto.setOfferId("123");
|
||||
dto.setEarnings(12f);
|
||||
dto.setVolume(123f);
|
||||
dto.setTransactionTime("2020-01-01 00:00:00");
|
||||
sqliteConnector.writeTX(dto);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getDataOrigin_ReturnsCorrectDataOrigin() {
|
||||
void outputTransactionsToLog_NothingThrown() {
|
||||
insertSampleTransaction();
|
||||
|
||||
assertDoesNotThrow(() -> {
|
||||
sqliteConnector.outputTransactionsToLog();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void outputSummaryToLog_NothingThrown() {
|
||||
insertSampleTransaction();
|
||||
|
||||
assertDoesNotThrow(() -> {
|
||||
sqliteConnector.outputSummaryToLog();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void outputTransactionsToLog_ThrowsPersistenceException_OnSQLException() throws SQLException {
|
||||
// Arrange
|
||||
SQLiteConnector connector = new SQLiteConnector(new SQLiteDataSource());
|
||||
sqliteConnector.setDb(mockDataSource);
|
||||
doThrow(SQLException.class).when(mockDataSource).getConnection();
|
||||
|
||||
// Act and Assert
|
||||
PersistenceException e = assertThrows(PersistenceException.class,
|
||||
() -> sqliteConnector.outputTransactionsToLog());
|
||||
assertEquals("Something went wrong while reading transaction from SQLite", e.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void outputSummaryToLog_ThrowsPersistenceException_OnSQLException() throws SQLException {
|
||||
// Arrange
|
||||
sqliteConnector.setDb(mockDataSource);
|
||||
doThrow(SQLException.class).when(mockDataSource).getConnection();
|
||||
|
||||
// Act and Assert
|
||||
PersistenceException e = assertThrows(PersistenceException.class,
|
||||
() -> sqliteConnector.outputSummaryToLog());
|
||||
assertEquals("Something went wrong while reading transaction summary from SQLite", e.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteOfferById_SuccessfulDelete() {
|
||||
// Arrange
|
||||
sqliteConnector.clearData();
|
||||
insertSampleOffer();
|
||||
|
||||
// Make sure it's there
|
||||
assertEquals(1, sqliteConnector.getOffers().size());
|
||||
|
||||
// Act
|
||||
String dataOrigin = connector.getDataOrigin();
|
||||
sqliteConnector.deleteOfferById("123");
|
||||
|
||||
// Assert
|
||||
assertEquals("SQLite", dataOrigin);
|
||||
assertEquals(0, sqliteConnector.getOffers().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getApiKey_UnsupportedOperationExceptionThrown() {
|
||||
// Arrange
|
||||
SQLiteConnector connector = new SQLiteConnector(new SQLiteDataSource());
|
||||
void deleteOfferById_ThrowsPersistenceException_OnSQLException() throws SQLException {
|
||||
sqliteConnector.setDb(mockDataSource);
|
||||
doThrow(SQLException.class).when(mockDataSource).getConnection();
|
||||
|
||||
// Act and Assert
|
||||
assertThrows(UnsupportedOperationException.class, connector::getApiKey);
|
||||
PersistenceException e = assertThrows(PersistenceException.class,
|
||||
() -> sqliteConnector.deleteOfferById("123"));
|
||||
assertEquals("Something went wrong while deleting offer from SQLite", e.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void buildProductDTO_UnsupportedOperationExceptionThrown() {
|
||||
// Arrange
|
||||
SQLiteConnector connector = new SQLiteConnector(new SQLiteDataSource());
|
||||
ProductDTO product = new ProductDTO("ASIN123", "Amazon");
|
||||
String json = "{\"productId\":\"ASIN123\",\"dataOrigin\":\"Amazon\"}";
|
||||
void getOffers_ReturnsCorrectValues() {
|
||||
sqliteConnector.clearData();
|
||||
assertEquals(0, sqliteConnector.getOffers().size());
|
||||
|
||||
// Act and Assert
|
||||
assertThrows(UnsupportedOperationException.class, () -> connector.buildProductDTO(product, json));
|
||||
insertSampleOffer();
|
||||
|
||||
assertEquals(1, sqliteConnector.getOffers().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void createApiUrl_UnsupportedOperationExceptionThrown() {
|
||||
// Arrange
|
||||
SQLiteConnector connector = new SQLiteConnector(new SQLiteDataSource());
|
||||
String productIdentifier = "ASIN123";
|
||||
void getOffers_ThrowsPersistenceException_OnSQLException() throws SQLException {
|
||||
sqliteConnector.setDb(mockDataSource);
|
||||
doThrow(SQLException.class).when(mockDataSource).getConnection();
|
||||
|
||||
// Act and Assert
|
||||
assertThrows(UnsupportedOperationException.class, () -> connector.createApiUrl(productIdentifier));
|
||||
PersistenceException e = assertThrows(PersistenceException.class,
|
||||
() -> sqliteConnector.getOffers());
|
||||
assertEquals("Something went wrong while reading offers from SQLite", e.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void writeOffer_ValidDTO_DataSavedToDatabase() throws SQLException {
|
||||
// Arrange
|
||||
OfferDTO offerDTO = new OfferDTO();
|
||||
offerDTO.setOfferId("123");
|
||||
offerDTO.setSourceProduct(new ProductDTO(TEST_PRODUCT_ID, Webshop.AMAZON));
|
||||
offerDTO.setTargetProduct(new ProductDTO(TEST_PRODUCT_ID, Webshop.AMAZON));
|
||||
|
||||
String expectedQuery = "INSERT INTO offers (offerId, sourceWebshop, sourceId, sourcePrice, " +
|
||||
"targetWebshop, targetId, targetPrice, lastupdate) VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
|
||||
when(connection.prepareStatement(expectedQuery)).thenReturn(statement);
|
||||
|
||||
// Act
|
||||
assertDoesNotThrow(() -> sqliteConnector.writeOffer(offerDTO));
|
||||
}
|
||||
|
||||
@Test
|
||||
void writeTX_NothingThrown() {
|
||||
TransactionDTO dto = new TransactionDTO();
|
||||
|
||||
assertDoesNotThrow(() -> {
|
||||
sqliteConnector.writeTX(dto);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void writeTX_ThrowsPersistenceException_OnSQLException() throws SQLException {
|
||||
// Arrange
|
||||
sqliteConnector.setDb(mockDataSource);
|
||||
doThrow(SQLException.class).when(mockDataSource).getConnection();
|
||||
TransactionDTO dto = new TransactionDTO();
|
||||
|
||||
// Act and Assert
|
||||
PersistenceException e = assertThrows(PersistenceException.class,
|
||||
() -> sqliteConnector.writeTX(dto));
|
||||
assertEquals("Something went wrong while saving transaction to SQLite", e.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getOfferDTOById_OfferExists_ReturnsProductDTO() {
|
||||
// Arrange
|
||||
sqliteConnector.clearData();
|
||||
insertSampleOffer();
|
||||
|
||||
// Act
|
||||
OfferDTO offerDTO = sqliteConnector.getOfferDTOById("123");
|
||||
|
||||
// Assert
|
||||
assertNotNull(offerDTO);
|
||||
assertEquals("123", offerDTO.getOfferId());
|
||||
assertEquals("2020-01-01 00:00:00", offerDTO.getLastUpdate());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 InvalidOfferExceptionTest {
|
||||
|
||||
@Test
|
||||
void constructor_WithMessage_SetsMessage() {
|
||||
// Arrange
|
||||
String message = "Invalid Offer data";
|
||||
|
||||
// Act
|
||||
InvalidOfferException exception = new InvalidOfferException(message);
|
||||
|
||||
// Assert
|
||||
assertEquals(message, exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void constructor_WithMessageAndCause_SetsMessageAndCause() {
|
||||
// Arrange
|
||||
String message = "Invalid Offer data";
|
||||
Throwable cause = new IllegalArgumentException("Invalid argument");
|
||||
|
||||
// Act
|
||||
InvalidOfferException exception = new InvalidOfferException(message, cause);
|
||||
|
||||
// Assert
|
||||
assertEquals(message, exception.getMessage());
|
||||
assertEquals(cause, exception.getCause());
|
||||
}
|
||||
|
||||
@Test
|
||||
void constructor_WithNullMessage_SetsNullMessage() {
|
||||
// Act
|
||||
InvalidOfferException exception = new InvalidOfferException(null);
|
||||
|
||||
// Assert
|
||||
assertEquals(null, exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void constructor_WithNullCause_SetsNullCause() {
|
||||
// Act
|
||||
InvalidOfferException exception = new InvalidOfferException("Invalid Offer data", null);
|
||||
|
||||
// Assert
|
||||
assertEquals(null, exception.getCause());
|
||||
}
|
||||
|
||||
@Test
|
||||
void throw_InvalidOfferException() {
|
||||
// Act and Assert
|
||||
assertThrows(InvalidOfferException.class, () -> {
|
||||
throw new InvalidOfferException("Invalid Offer data");
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -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 InvalidTransactionExceptionTest {
|
||||
|
||||
@Test
|
||||
void constructor_WithMessage_SetsMessage() {
|
||||
// Arrange
|
||||
String message = "Invalid Transaction data";
|
||||
|
||||
// Act
|
||||
InvalidTransactionException exception = new InvalidTransactionException(message);
|
||||
|
||||
// Assert
|
||||
assertEquals(message, exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void constructor_WithMessageAndCause_SetsMessageAndCause() {
|
||||
// Arrange
|
||||
String message = "Invalid Transaction data";
|
||||
Throwable cause = new IllegalArgumentException("Invalid argument");
|
||||
|
||||
// Act
|
||||
InvalidTransactionException exception = new InvalidTransactionException(message, cause);
|
||||
|
||||
// Assert
|
||||
assertEquals(message, exception.getMessage());
|
||||
assertEquals(cause, exception.getCause());
|
||||
}
|
||||
|
||||
@Test
|
||||
void constructor_WithNullMessage_SetsNullMessage() {
|
||||
// Act
|
||||
InvalidTransactionException exception = new InvalidTransactionException(null);
|
||||
|
||||
// Assert
|
||||
assertEquals(null, exception.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void constructor_WithNullCause_SetsNullCause() {
|
||||
// Act
|
||||
InvalidTransactionException exception = new InvalidTransactionException("Invalid Transaction data", null);
|
||||
|
||||
// Assert
|
||||
assertEquals(null, exception.getCause());
|
||||
}
|
||||
|
||||
@Test
|
||||
void throw_InvalidTransactionException() {
|
||||
// Act and Assert
|
||||
assertThrows(InvalidTransactionException.class, () -> {
|
||||
throw new InvalidTransactionException("Invalid Transaction data");
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package de.rwu.easydrop.model;
|
||||
|
||||
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
@@ -19,7 +21,7 @@ class ProductCatalogueTest {
|
||||
Product product = new Product();
|
||||
product.setProductId("12345");
|
||||
product.setMerchant("AmazonSeller");
|
||||
product.setDataOrigin("Amazon");
|
||||
product.setDataOrigin(Webshop.AMAZON);
|
||||
productCatalogue.addProduct(product);
|
||||
|
||||
List<Product> products = productCatalogue.getProducts();
|
||||
@@ -32,13 +34,13 @@ class ProductCatalogueTest {
|
||||
Product product1 = new Product();
|
||||
product1.setProductId("12345");
|
||||
product1.setMerchant("AmazonSeller");
|
||||
product1.setDataOrigin("Amazon");
|
||||
product1.setDataOrigin(Webshop.AMAZON);
|
||||
productCatalogue.addProduct(product1);
|
||||
|
||||
Product product2 = new Product();
|
||||
product2.setProductId("54321");
|
||||
product2.setMerchant("eBaySeller");
|
||||
product2.setDataOrigin("eBay");
|
||||
product2.setDataOrigin(Webshop.EBAY);
|
||||
productCatalogue.addProduct(product2);
|
||||
|
||||
productCatalogue.removeProduct(product1);
|
||||
@@ -53,13 +55,13 @@ class ProductCatalogueTest {
|
||||
Product product1 = new Product();
|
||||
product1.setProductId("12345");
|
||||
product1.setMerchant("AmazonSeller");
|
||||
product1.setDataOrigin("Amazon");
|
||||
product1.setDataOrigin(Webshop.AMAZON);
|
||||
productCatalogue.addProduct(product1);
|
||||
|
||||
Product product2 = new Product();
|
||||
product2.setProductId("54321");
|
||||
product2.setMerchant("eBay");
|
||||
product2.setDataOrigin("eBay");
|
||||
product2.setMerchant("ebayMerchant");
|
||||
product2.setDataOrigin(Webshop.EBAY);
|
||||
productCatalogue.addProduct(product2);
|
||||
|
||||
productCatalogue.clearProducts();
|
||||
@@ -73,20 +75,23 @@ class ProductCatalogueTest {
|
||||
Product product1 = new Product();
|
||||
product1.setProductId("12345");
|
||||
product1.setMerchant("AmazonSeller");
|
||||
product1.setDataOrigin("Amazon");
|
||||
product1.setDataOrigin(Webshop.AMAZON);
|
||||
productCatalogue.addProduct(product1);
|
||||
|
||||
Product product2 = new Product();
|
||||
product2.setProductId("54321");
|
||||
product2.setMerchant("eBaySeller");
|
||||
product2.setDataOrigin("eBay");
|
||||
product2.setDataOrigin(Webshop.EBAY);
|
||||
productCatalogue.addProduct(product2);
|
||||
|
||||
String expectedString = "Product Catalogue: GPU\n" +
|
||||
"Description: Graphics Processing Units\n" +
|
||||
"Products:\n" +
|
||||
"Product: [12345 from AmazonSeller (Amazon) at 0,00 Euro (available: no)]\n" +
|
||||
"Product: [54321 from eBaySeller (eBay) at 0,00 Euro (available: no)]\n";
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(String.format("Catalogue Name: %s%n", "GPU"));
|
||||
sb.append(String.format("Description: %s%n", "Graphics Processing Units"));
|
||||
sb.append("Products:\n");
|
||||
sb.append(String.format("%s%n", product1.toString()));
|
||||
sb.append(String.format("%s%n", product2.toString()));
|
||||
|
||||
String expectedString = sb.toString();
|
||||
|
||||
Assertions.assertEquals(expectedString, productCatalogue.toString());
|
||||
}
|
||||
|
||||
25
src/test/java/de/rwu/easydrop/model/ProductPairTest.java
Normal file
25
src/test/java/de/rwu/easydrop/model/ProductPairTest.java
Normal file
@@ -0,0 +1,25 @@
|
||||
package de.rwu.easydrop.model;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class ProductPairTest {
|
||||
|
||||
@Test
|
||||
void constructor_TwoProducts_ProductsInitializedCorrectly() {
|
||||
// Arrange
|
||||
Product product1 = new Product();
|
||||
product1.setProductId("123");
|
||||
|
||||
Product product2 = new Product();
|
||||
product2.setProductId("234");
|
||||
|
||||
// Act
|
||||
ProductPair pair = new ProductPair(product1, product2);
|
||||
|
||||
// Assert
|
||||
assertSame(product1, pair.getProduct1());
|
||||
assertSame(product2, pair.getProduct2());
|
||||
}
|
||||
}
|
||||
@@ -10,13 +10,13 @@ class ProductTest {
|
||||
@Test
|
||||
void testToString1() {
|
||||
Product product1 = new Product();
|
||||
product1.setDataOrigin("Amazon");
|
||||
product1.setDataOrigin(Webshop.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 Euro (available: yes)]";
|
||||
String expectedString1 = "Product: [12345 from Merchant A (AMAZON) at 19,99 Euro (available: yes)]";
|
||||
String result1 = product1.toString();
|
||||
|
||||
assertEquals(expectedString1, result1);
|
||||
@@ -25,13 +25,13 @@ class ProductTest {
|
||||
@Test
|
||||
void testToString2() {
|
||||
Product product2 = new Product();
|
||||
product2.setDataOrigin("eBay");
|
||||
product2.setDataOrigin(Webshop.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 Euro (available: no)]";
|
||||
String expectedString2 = "Product: [67890 from Merchant B (EBAY) at 9,99 Euro (available: no)]";
|
||||
String result2 = product2.toString();
|
||||
|
||||
assertEquals(expectedString2, result2);
|
||||
@@ -41,7 +41,7 @@ class ProductTest {
|
||||
void gettersAndSetters_WorkAsExpected() {
|
||||
// Arrange
|
||||
Product product = new Product();
|
||||
product.setDataOrigin("Amazon");
|
||||
product.setDataOrigin(Webshop.AMAZON);
|
||||
product.setProductId("12345");
|
||||
product.setCurrentPrice(9.99);
|
||||
product.setMerchant("Example Merchant");
|
||||
@@ -49,7 +49,7 @@ class ProductTest {
|
||||
product.setAvailable(true);
|
||||
|
||||
// Act and Assert
|
||||
assertEquals("Amazon", product.getDataOrigin());
|
||||
assertEquals(Webshop.AMAZON, product.getDataOrigin());
|
||||
assertEquals("12345", product.getProductId());
|
||||
assertEquals(9.99, product.getCurrentPrice());
|
||||
assertEquals("Example Merchant", product.getMerchant());
|
||||
@@ -57,7 +57,7 @@ class ProductTest {
|
||||
assertTrue(product.isAvailable());
|
||||
|
||||
// Modify fields
|
||||
product.setDataOrigin("eBay");
|
||||
product.setDataOrigin(Webshop.EBAY);
|
||||
product.setProductId("54321");
|
||||
product.setCurrentPrice(19.99);
|
||||
product.setMerchant("New Merchant");
|
||||
@@ -65,7 +65,7 @@ class ProductTest {
|
||||
product.setAvailable(false);
|
||||
|
||||
// Assert
|
||||
assertEquals("eBay", product.getDataOrigin());
|
||||
assertEquals(Webshop.EBAY, product.getDataOrigin());
|
||||
assertEquals("54321", product.getProductId());
|
||||
assertEquals(19.99, product.getCurrentPrice());
|
||||
assertEquals("New Merchant", product.getMerchant());
|
||||
|
||||
23
src/test/java/de/rwu/easydrop/model/WebshopTest.java
Normal file
23
src/test/java/de/rwu/easydrop/model/WebshopTest.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package de.rwu.easydrop.model;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class WebshopTest {
|
||||
|
||||
@Test
|
||||
void testFromString_returnsIntendedConstant() {
|
||||
Webshop testShop = Webshop.fromString("Amazon");
|
||||
|
||||
assertEquals(Webshop.AMAZON, testShop);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFromString_invalidShop() {
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
Webshop.fromString("thisdoesnotexist");
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
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.OfferDTO;
|
||||
import de.rwu.easydrop.model.Offer;
|
||||
import de.rwu.easydrop.model.Product;
|
||||
import de.rwu.easydrop.model.Webshop;
|
||||
|
||||
class OfferMapperTest {
|
||||
|
||||
@Test
|
||||
void testConstructorIsPrivate()
|
||||
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
|
||||
// Check for private constructor
|
||||
Constructor<OfferMapper> constructor = OfferMapper.class.getDeclaredConstructor();
|
||||
assertTrue(Modifier.isPrivate(constructor.getModifiers()));
|
||||
|
||||
// Make sure exception is thrown when instantiating
|
||||
constructor.setAccessible(true);
|
||||
assertThrows(InvocationTargetException.class, () -> {
|
||||
constructor.newInstance();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void mapOfferToDTO() {
|
||||
// Arrange
|
||||
Product product = new Product();
|
||||
product.setProductId("12345");
|
||||
product.setDataOrigin(Webshop.AMAZON);
|
||||
product.setAvailable(true);
|
||||
product.setCurrentPrice(9.99);
|
||||
product.setDeliveryPrice(2.50);
|
||||
product.setMerchant("Seller1");
|
||||
|
||||
Offer offer = new Offer();
|
||||
offer.setOfferId("68735");
|
||||
offer.setLastUpdate("2020-07-07");
|
||||
offer.setSourceProduct(product);
|
||||
offer.setTargetProduct(product);
|
||||
|
||||
// Act
|
||||
OfferDTO dto = OfferMapper.mapOfferToDTO(offer);
|
||||
|
||||
// Assert
|
||||
assertEquals("68735", dto.getOfferId());
|
||||
assertEquals("2020-07-07", dto.getLastUpdate());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import org.junit.jupiter.api.Test;
|
||||
import de.rwu.easydrop.api.dto.ProductDTO;
|
||||
|
||||
import de.rwu.easydrop.model.Product;
|
||||
import de.rwu.easydrop.model.Webshop;
|
||||
|
||||
class ProductMapperTest {
|
||||
@Test
|
||||
@@ -47,7 +48,7 @@ class ProductMapperTest {
|
||||
}
|
||||
|
||||
private ProductDTO createProductDTO() {
|
||||
ProductDTO dto = new ProductDTO("12345", "Amazon");
|
||||
ProductDTO dto = new ProductDTO("12345", Webshop.AMAZON);
|
||||
dto.setAvailable(true);
|
||||
dto.setCurrentPrice(9.99);
|
||||
dto.setDeliveryPrice(2.50);
|
||||
@@ -60,7 +61,7 @@ class ProductMapperTest {
|
||||
// Arrange
|
||||
Product product = new Product();
|
||||
product.setProductId("12345");
|
||||
product.setDataOrigin("Amazon");
|
||||
product.setDataOrigin(Webshop.AMAZON);
|
||||
product.setAvailable(true);
|
||||
product.setCurrentPrice(9.99);
|
||||
product.setDeliveryPrice(2.50);
|
||||
@@ -71,7 +72,7 @@ class ProductMapperTest {
|
||||
|
||||
// Assert
|
||||
assertEquals("12345", dto.getProductId());
|
||||
assertEquals("Amazon", dto.getDataOrigin());
|
||||
assertEquals(Webshop.AMAZON, dto.getDataOrigin());
|
||||
assertTrue(dto.isAvailable());
|
||||
assertEquals(9.99, dto.getCurrentPrice());
|
||||
assertEquals(2.50, dto.getDeliveryPrice());
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
package de.rwu.easydrop.service.mapping;
|
||||
|
||||
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.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.TransactionDTO;
|
||||
import de.rwu.easydrop.model.Transaction;
|
||||
|
||||
class TransactionMapperTest {
|
||||
@Test
|
||||
void testConstructorIsPrivate()
|
||||
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
|
||||
// Check for private constructor
|
||||
Constructor<TransactionMapper> constructor = TransactionMapper.class.getDeclaredConstructor();
|
||||
assertTrue(Modifier.isPrivate(constructor.getModifiers()));
|
||||
|
||||
// Make sure exception is thrown when instantiating
|
||||
constructor.setAccessible(true);
|
||||
assertThrows(InvocationTargetException.class, () -> {
|
||||
constructor.newInstance();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void mapTXFromDTO_WithValidTransactionDTO_ReturnsTransaction() {
|
||||
// Arrange
|
||||
TransactionDTO transactionDTO = new TransactionDTO();
|
||||
transactionDTO.setOfferId("123");
|
||||
transactionDTO.setVolume(10.0);
|
||||
transactionDTO.setEarnings(5.0);
|
||||
transactionDTO.setTransactionTime("2023-06-25 03:26:59");
|
||||
|
||||
// Act
|
||||
Transaction transaction = TransactionMapper.mapTXFromDTO(transactionDTO);
|
||||
|
||||
// Assert
|
||||
assertNotNull(transaction);
|
||||
assertEquals(transactionDTO.getOfferId(), transaction.getOfferId());
|
||||
assertEquals(transactionDTO.getVolume(), transaction.getVolume());
|
||||
assertEquals(transactionDTO.getEarnings(), transaction.getEarnings());
|
||||
assertEquals(transactionDTO.getTransactionTime(), transaction.getTransactionTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
void mapTXToDTO_WithValidTransaction_ReturnsTransactionDTO() {
|
||||
// Arrange
|
||||
Transaction transaction = new Transaction();
|
||||
transaction.setOfferId("123");
|
||||
transaction.setVolume(10.0);
|
||||
transaction.setEarnings(5.0);
|
||||
transaction.setTransactionTime("2023-06-25 03:26:59");
|
||||
|
||||
// Act
|
||||
TransactionDTO transactionDTO = TransactionMapper.mapTXToDTO(transaction);
|
||||
|
||||
// Assert
|
||||
assertNotNull(transactionDTO);
|
||||
assertEquals(transaction.getOfferId(), transactionDTO.getOfferId());
|
||||
assertEquals(transaction.getVolume(), transactionDTO.getVolume());
|
||||
assertEquals(transaction.getEarnings(), transactionDTO.getEarnings());
|
||||
assertEquals(transaction.getTransactionTime(), transactionDTO.getTransactionTime());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
package de.rwu.easydrop.service.processing;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import de.rwu.easydrop.exception.InvalidCatalogueException;
|
||||
import de.rwu.easydrop.exception.InvalidOfferException;
|
||||
import de.rwu.easydrop.model.Offer;
|
||||
import de.rwu.easydrop.model.Product;
|
||||
import de.rwu.easydrop.model.ProductCatalogue;
|
||||
import de.rwu.easydrop.model.ProductPair;
|
||||
|
||||
class OfferIdentifierTest {
|
||||
|
||||
@Mock
|
||||
private ProductCatalogue mockProductCatalogue;
|
||||
|
||||
private OfferIdentifier offerIdentifier;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
MockitoAnnotations.openMocks(this);
|
||||
|
||||
offerIdentifier = new OfferIdentifier();
|
||||
}
|
||||
|
||||
@Test
|
||||
void runIdentifier_WithValidProductCatalogues_IdentifiesOffers() {
|
||||
// Arrange
|
||||
List<ProductCatalogue> productCatalogues = new ArrayList<>();
|
||||
ProductCatalogue productCatalogue1 = new ProductCatalogue("Catalogue1", "desc");
|
||||
ProductCatalogue productCatalogue2 = new ProductCatalogue("Catalogue2", "desc");
|
||||
|
||||
Product product1 = new Product();
|
||||
product1.setCurrentPrice(100.0);
|
||||
Product product2 = new Product();
|
||||
product2.setCurrentPrice(200.0);
|
||||
Product product3 = new Product();
|
||||
product3.setCurrentPrice(300.0);
|
||||
Product product4 = new Product();
|
||||
product4.setCurrentPrice(400.0);
|
||||
|
||||
productCatalogue1.addProduct(product1);
|
||||
productCatalogue1.addProduct(product2);
|
||||
productCatalogue2.addProduct(product3);
|
||||
productCatalogue2.addProduct(product4);
|
||||
|
||||
productCatalogues.add(productCatalogue1);
|
||||
productCatalogues.add(productCatalogue2);
|
||||
|
||||
// Act
|
||||
List<Offer> identifiedOffers = offerIdentifier.runIdentifier(productCatalogues);
|
||||
|
||||
// Assert
|
||||
assertEquals(2, identifiedOffers.size());
|
||||
assertNotNull(identifiedOffers.get(0).getSourceProduct());
|
||||
assertNotNull(identifiedOffers.get(0).getTargetProduct());
|
||||
assertNotNull(identifiedOffers.get(1).getSourceProduct());
|
||||
assertNotNull(identifiedOffers.get(1).getTargetProduct());
|
||||
}
|
||||
|
||||
@Test
|
||||
void runIdentifier_WithOneGoodOneBadCatalogue_BadOneIsntIncluded() {
|
||||
// Arrange
|
||||
List<ProductCatalogue> productCatalogues = new ArrayList<>();
|
||||
ProductCatalogue productCatalogue1 = new ProductCatalogue("Catalogue1", "desc");
|
||||
ProductCatalogue productCatalogue2 = new ProductCatalogue("Catalogue2", "desc");
|
||||
|
||||
Product product1 = new Product();
|
||||
product1.setCurrentPrice(100.0);
|
||||
Product product2 = new Product();
|
||||
product2.setCurrentPrice(200.0);
|
||||
Product product3 = new Product();
|
||||
product3.setCurrentPrice(300.0);
|
||||
Product product4 = new Product();
|
||||
product4.setCurrentPrice(300.0);
|
||||
|
||||
productCatalogue1.addProduct(product1);
|
||||
productCatalogue1.addProduct(product2);
|
||||
productCatalogue2.addProduct(product3);
|
||||
productCatalogue2.addProduct(product4);
|
||||
|
||||
productCatalogues.add(productCatalogue1);
|
||||
productCatalogues.add(productCatalogue2);
|
||||
|
||||
// Act
|
||||
List<Offer> identifiedOffers = offerIdentifier.runIdentifier(productCatalogues);
|
||||
|
||||
// Assert
|
||||
assertEquals(1, identifiedOffers.size()); // Only 1 passed
|
||||
}
|
||||
|
||||
@Test
|
||||
void getHighestMarginProducts_WithValidProductCatalogue_ReturnsProductPair() {
|
||||
// Arrange
|
||||
ProductCatalogue productCatalogue = new ProductCatalogue("TestCatalogue", "desc");
|
||||
Product product1 = new Product();
|
||||
product1.setCurrentPrice(100.0);
|
||||
Product product2 = new Product();
|
||||
product2.setCurrentPrice(200.0);
|
||||
productCatalogue.addProduct(product1);
|
||||
productCatalogue.addProduct(product2);
|
||||
|
||||
// Act
|
||||
ProductPair productPair = OfferIdentifier.getHighestMarginProducts(productCatalogue);
|
||||
|
||||
// Assert
|
||||
assertNotNull(productPair);
|
||||
assertNotNull(productPair.getProduct1());
|
||||
assertNotNull(productPair.getProduct2());
|
||||
assertNotEquals(productPair.getProduct1(), productPair.getProduct2());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getHighestMarginProducts_SecondProductCheaper() {
|
||||
// Arrange
|
||||
ProductCatalogue productCatalogue = new ProductCatalogue("TestCatalogue", "desc");
|
||||
Product product1 = new Product();
|
||||
product1.setCurrentPrice(200.0);
|
||||
Product product2 = new Product();
|
||||
product2.setCurrentPrice(100.0);
|
||||
productCatalogue.addProduct(product1);
|
||||
productCatalogue.addProduct(product2);
|
||||
|
||||
// Act
|
||||
ProductPair productPair = OfferIdentifier.getHighestMarginProducts(productCatalogue);
|
||||
|
||||
// Assert
|
||||
assertNotNull(productPair);
|
||||
assertNotNull(productPair.getProduct1());
|
||||
assertNotNull(productPair.getProduct2());
|
||||
assertNotEquals(productPair.getProduct1(), productPair.getProduct2());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getHighestMarginProducts_WithCatalogueSizeLessThan2_ThrowsInvalidCatalogueException() {
|
||||
// Arrange
|
||||
ProductCatalogue productCatalogue = new ProductCatalogue("SmallCatalogue", "desc");
|
||||
|
||||
// Act and Assert
|
||||
assertThrows(InvalidCatalogueException.class, () -> {
|
||||
OfferIdentifier.getHighestMarginProducts(productCatalogue);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void getHighestMarginProducts_WithZeroPriceMargin_ThrowsInvalidOfferException() {
|
||||
// Arrange
|
||||
ProductCatalogue productCatalogue = new ProductCatalogue("name", "desc");
|
||||
Product product1 = new Product();
|
||||
product1.setCurrentPrice(200.0);
|
||||
|
||||
Product product2 = new Product();
|
||||
product2.setCurrentPrice(200.0);
|
||||
|
||||
productCatalogue.getProducts().add(product1);
|
||||
productCatalogue.getProducts().add(product2);
|
||||
|
||||
// Act and Assert
|
||||
InvalidOfferException e = assertThrows(InvalidOfferException.class, () -> {
|
||||
OfferIdentifier.getHighestMarginProducts(productCatalogue);
|
||||
});
|
||||
|
||||
assertEquals("Price margin is zero!", e.getMessage());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
package de.rwu.easydrop.service.processing;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
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.AmazonPurchaser;
|
||||
import de.rwu.easydrop.api.client.AmazonSeller;
|
||||
import de.rwu.easydrop.api.client.EbayPurchaser;
|
||||
import de.rwu.easydrop.api.client.EbaySeller;
|
||||
import de.rwu.easydrop.api.client.PurchaserFactory;
|
||||
import de.rwu.easydrop.api.client.SellerFactory;
|
||||
import de.rwu.easydrop.data.connector.OfferPersistenceInterface;
|
||||
import de.rwu.easydrop.model.Offer;
|
||||
import de.rwu.easydrop.model.Product;
|
||||
import de.rwu.easydrop.model.Webshop;
|
||||
import de.rwu.easydrop.service.writer.OfferWriter;
|
||||
|
||||
class OfferProvisionerTest {
|
||||
|
||||
@Mock
|
||||
private OfferPersistenceInterface mockPersistence;
|
||||
|
||||
@Mock
|
||||
private SellerFactory mockSellerFactory;
|
||||
|
||||
@Mock
|
||||
private PurchaserFactory mockPurchaserFactory;
|
||||
|
||||
@Mock
|
||||
private OfferWriter mockOfferWriter;
|
||||
|
||||
@Mock
|
||||
private AmazonSeller mockAmazonSeller;
|
||||
|
||||
@Mock
|
||||
private EbaySeller mockEbaySeller;
|
||||
|
||||
@Mock
|
||||
private AmazonPurchaser mockAmazonPurchaser;
|
||||
|
||||
@Mock
|
||||
private EbayPurchaser mockEbayPurchaser;
|
||||
|
||||
private OfferProvisioner offerProvisioner;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
MockitoAnnotations.openMocks(this);
|
||||
|
||||
when(mockSellerFactory.createAmazonSeller()).thenReturn(mockAmazonSeller);
|
||||
when(mockSellerFactory.createEbaySeller()).thenReturn(mockEbaySeller);
|
||||
when(mockPurchaserFactory.createAmazonPurchaser()).thenReturn(mockAmazonPurchaser);
|
||||
when(mockPurchaserFactory.createEbayPurchaser()).thenReturn(mockEbayPurchaser);
|
||||
|
||||
offerProvisioner = new OfferProvisioner(mockPersistence, mockSellerFactory, mockPurchaserFactory);
|
||||
offerProvisioner.setOfferWriter(mockOfferWriter);
|
||||
}
|
||||
|
||||
@Test
|
||||
void runProvisioner_WithValidOffers_PlacesOrders() {
|
||||
// Arrange
|
||||
List<Offer> offers = new ArrayList<>();
|
||||
Offer offer1 = createOffer(Webshop.AMAZON, "ASIN123", Webshop.EBAY, "12345");
|
||||
Offer offer2 = createOffer(Webshop.EBAY, "54321", Webshop.AMAZON, "ASIN456");
|
||||
offers.add(offer1);
|
||||
offers.add(offer2);
|
||||
|
||||
// Act
|
||||
offerProvisioner.runProvisioner(offers);
|
||||
|
||||
// Assert
|
||||
verify(mockAmazonSeller, times(1)).sellProduct(any());
|
||||
verify(mockEbaySeller, times(1)).sellProduct(any());
|
||||
verify(mockAmazonPurchaser, times(1)).purchaseProduct(any());
|
||||
verify(mockEbayPurchaser, times(1)).purchaseProduct(any());
|
||||
verify(mockOfferWriter, times(2)).writeOfferToPersistence(any());
|
||||
}
|
||||
|
||||
private Offer createOffer(Webshop sourceWebshop, String sourceProductId, Webshop targetWebshop,
|
||||
String targetProductId) {
|
||||
Product sourceProduct = new Product();
|
||||
sourceProduct.setDataOrigin(sourceWebshop);
|
||||
sourceProduct.setProductId(sourceProductId);
|
||||
|
||||
Product targetProduct = new Product();
|
||||
targetProduct.setDataOrigin(targetWebshop);
|
||||
targetProduct.setProductId(targetProductId);
|
||||
|
||||
Offer offer = new Offer();
|
||||
offer.setSourceProduct(sourceProduct);
|
||||
offer.setTargetProduct(targetProduct);
|
||||
|
||||
return offer;
|
||||
}
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
package de.rwu.easydrop.service.processing;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
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.assertTrue;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import de.rwu.easydrop.exception.InvalidCatalogueException;
|
||||
import de.rwu.easydrop.model.Product;
|
||||
import de.rwu.easydrop.model.ProductCatalogue;
|
||||
import de.rwu.easydrop.model.ProductPair;
|
||||
|
||||
class OrderManagerTest {
|
||||
|
||||
@Test
|
||||
void testConstructorIsPrivate()
|
||||
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
|
||||
// Check for private constructor
|
||||
Constructor<OrderManager> constructor = OrderManager.class.getDeclaredConstructor();
|
||||
assertTrue(Modifier.isPrivate(constructor.getModifiers()));
|
||||
|
||||
// Make sure exception is thrown when instantiating
|
||||
constructor.setAccessible(true);
|
||||
assertThrows(InvocationTargetException.class, () -> {
|
||||
constructor.newInstance();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateOrders_ValidCatalogues_OrdersCreated() {
|
||||
// Arrange
|
||||
List<ProductCatalogue> catalogues = createSampleCatalogues();
|
||||
|
||||
// Act
|
||||
assertDoesNotThrow(() -> {
|
||||
OrderManager.createOrders(catalogues);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetHighestMarginProducts_ValidCatalogue_CheapestAndMostExpensiveProductsReturned() {
|
||||
// Arrange
|
||||
ProductCatalogue catalogue = createSampleCatalogue();
|
||||
|
||||
// Act
|
||||
ProductPair pair = OrderManager.getHighestMarginProducts(catalogue);
|
||||
|
||||
// Assert
|
||||
assertNotNull(pair);
|
||||
assertNotNull(pair.getProduct1());
|
||||
assertNotNull(pair.getProduct2());
|
||||
assertEquals("Product2", pair.getProduct1().getProductId());
|
||||
assertEquals("Product3", pair.getProduct2().getProductId());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetHighestMarginProducts_InvalidCatalogue_ThrowsInvalidCatalogueException() {
|
||||
// Arrange
|
||||
ProductCatalogue catalogue = new ProductCatalogue("Catalogue1", "Sample catalogue");
|
||||
catalogue.addProduct(new Product());
|
||||
// The catalogue has only one product, which is invalid
|
||||
|
||||
// Act & Assert
|
||||
Exception e = assertThrows(InvalidCatalogueException.class,
|
||||
() -> OrderManager.getHighestMarginProducts(catalogue));
|
||||
|
||||
assertEquals("Product Catalogue holds less than 2 products!", e.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetHighestMarginProducts_InvalidCatalogue_NoMargin() {
|
||||
// Arrange
|
||||
ProductCatalogue catalogue = new ProductCatalogue("Catalogue1", "Sample catalogue");
|
||||
catalogue.addProduct(new Product());
|
||||
catalogue.addProduct(new Product());
|
||||
// The catalogue has only one product, which is invalid
|
||||
|
||||
// Act & Assert
|
||||
Exception e = assertThrows(InvalidCatalogueException.class,
|
||||
() -> OrderManager.getHighestMarginProducts(catalogue));
|
||||
|
||||
assertEquals("Price margin is zero!", e.getMessage());
|
||||
}
|
||||
|
||||
private List<ProductCatalogue> createSampleCatalogues() {
|
||||
List<ProductCatalogue> catalogues = new ArrayList<>();
|
||||
|
||||
ProductCatalogue catalogue1 = createSampleCatalogue();
|
||||
catalogues.add(catalogue1);
|
||||
|
||||
ProductCatalogue catalogue2 = new ProductCatalogue("Catalogue2", "Sample catalogue 2");
|
||||
Product product4 = new Product();
|
||||
product4.setProductId("Product4");
|
||||
product4.setCurrentPrice(6.78);
|
||||
catalogue2.addProduct(product4);
|
||||
Product product5 = new Product();
|
||||
product5.setProductId("Product5");
|
||||
product5.setCurrentPrice(7.89);
|
||||
catalogue2.addProduct(product5);
|
||||
catalogues.add(catalogue2);
|
||||
|
||||
return catalogues;
|
||||
}
|
||||
|
||||
private ProductCatalogue createSampleCatalogue() {
|
||||
ProductCatalogue catalogue = new ProductCatalogue("Catalogue1", "Sample catalogue");
|
||||
Product product1 = new Product();
|
||||
product1.setProductId("Product1");
|
||||
product1.setCurrentPrice(1.23);
|
||||
catalogue.addProduct(product1);
|
||||
Product product2 = new Product();
|
||||
product2.setProductId("Product2");
|
||||
product2.setCurrentPrice(0.89);
|
||||
catalogue.addProduct(product2);
|
||||
Product product3 = new Product();
|
||||
product3.setProductId("Product3");
|
||||
product3.setCurrentPrice(4.56);
|
||||
catalogue.addProduct(product3);
|
||||
return catalogue;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package de.rwu.easydrop.service.processing;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import de.rwu.easydrop.api.dto.TransactionDTO;
|
||||
import de.rwu.easydrop.data.connector.TransactionPersistenceInterface;
|
||||
import de.rwu.easydrop.model.Offer;
|
||||
import de.rwu.easydrop.model.Product;
|
||||
import de.rwu.easydrop.model.Transaction;
|
||||
import de.rwu.easydrop.service.mapping.TransactionMapper;
|
||||
|
||||
class TransactionHandlerTest {
|
||||
|
||||
@Mock
|
||||
private TransactionPersistenceInterface mockPersistence;
|
||||
|
||||
public TransactionHandlerTest() {
|
||||
MockitoAnnotations.openMocks(this);
|
||||
}
|
||||
|
||||
@Test
|
||||
void turnOfferToTransaction_ValidOffer_TransactionCreatedAndWrittenToPersistence() {
|
||||
// Arrange
|
||||
Offer offer = new Offer();
|
||||
Product product = new Product();
|
||||
offer.setSourceProduct(product);
|
||||
offer.setTargetProduct(product);
|
||||
|
||||
TransactionHandler handler = new TransactionHandler(mockPersistence);
|
||||
|
||||
// Act
|
||||
handler.turnOfferToTransaction(offer);
|
||||
|
||||
// Assert
|
||||
ArgumentCaptor<TransactionDTO> transactionDtoCaptor = ArgumentCaptor.forClass(TransactionDTO.class);
|
||||
verify(mockPersistence, times(1)).writeTX(transactionDtoCaptor.capture());
|
||||
|
||||
TransactionDTO capturedTransactionDto = transactionDtoCaptor.getValue();
|
||||
Transaction capturedTransaction = TransactionMapper.mapTXFromDTO(capturedTransactionDto);
|
||||
|
||||
assertEquals(offer.getOfferId(), capturedTransaction.getOfferId());
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package de.rwu.easydrop.service.retriever;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
@@ -14,9 +13,9 @@ import javax.naming.ConfigurationException;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import de.rwu.easydrop.exception.InvalidProductException;
|
||||
import de.rwu.easydrop.model.Product;
|
||||
import de.rwu.easydrop.model.ProductCatalogue;
|
||||
import de.rwu.easydrop.model.Webshop;
|
||||
import de.rwu.easydrop.util.ProductsConfig;
|
||||
|
||||
class CatalogueRetrieverTest {
|
||||
@@ -39,20 +38,20 @@ class CatalogueRetrieverTest {
|
||||
// Create a sample product catalogue with two products
|
||||
ProductCatalogue productCatalogue = new ProductCatalogue("Catalogue 1", "Sample catalogue");
|
||||
Product product1 = new Product();
|
||||
product1.setDataOrigin("Amazon");
|
||||
product1.setDataOrigin(Webshop.AMAZON);
|
||||
product1.setProductId("ASIN1");
|
||||
productCatalogue.addProduct(product1);
|
||||
|
||||
Product product2 = new Product();
|
||||
product2.setDataOrigin("eBay");
|
||||
product2.setDataOrigin(Webshop.EBAY);
|
||||
product2.setProductId("ProductID2");
|
||||
productCatalogue.addProduct(product2);
|
||||
productCatalogues.add(productCatalogue);
|
||||
|
||||
// Mock the methods
|
||||
when(productsConfig.getProductCatalogues()).thenReturn(productCatalogues);
|
||||
when(productRetriever.getProductFromAmazon("ASIN1")).thenReturn(product1);
|
||||
when(productRetriever.getProductFromEbay("ProductID2")).thenReturn(product2);
|
||||
when(productRetriever.getProductFromWebshop(Webshop.AMAZON, "ASIN1")).thenReturn(product1);
|
||||
when(productRetriever.getProductFromWebshop(Webshop.EBAY, "ProductID2")).thenReturn(product2);
|
||||
|
||||
// Act
|
||||
catalogueRetriever.loadCatalogues();
|
||||
@@ -71,33 +70,7 @@ class CatalogueRetrieverTest {
|
||||
|
||||
// Verify the method invocations
|
||||
verify(productsConfig).loadConfig();
|
||||
verify(productRetriever).getProductFromAmazon("ASIN1");
|
||||
verify(productRetriever).getProductFromEbay("ProductID2");
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadCatalogues_ValidConfig_CataloguesLoaded_InvalidProduct() throws ConfigurationException {
|
||||
// Arrange
|
||||
List<ProductCatalogue> productCatalogues = new ArrayList<>();
|
||||
|
||||
// Create a sample product catalogue
|
||||
ProductCatalogue productCatalogue = new ProductCatalogue("Catalogue 1", "Sample catalogue");
|
||||
|
||||
Product product = new Product();
|
||||
product.setDataOrigin("");
|
||||
product.setProductId("ProductID1");
|
||||
productCatalogue.addProduct(product);
|
||||
productCatalogues.add(productCatalogue);
|
||||
|
||||
// Mock the methods
|
||||
when(productsConfig.getProductCatalogues()).thenReturn(productCatalogues);
|
||||
when(productRetriever.getProductFromAmazon("ProductID1")).thenReturn(product);
|
||||
|
||||
// Act and Assert
|
||||
InvalidProductException exception = assertThrows(InvalidProductException.class, () -> {
|
||||
catalogueRetriever.loadCatalogues();
|
||||
});
|
||||
|
||||
assertEquals("Product data origin is invalid", exception.getMessage());
|
||||
verify(productRetriever).getProductFromWebshop(Webshop.AMAZON, "ASIN1");
|
||||
verify(productRetriever).getProductFromWebshop(Webshop.EBAY, "ProductID2");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
package de.rwu.easydrop.service.retriever;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
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.OfferDTO;
|
||||
import de.rwu.easydrop.api.dto.ProductDTO;
|
||||
import de.rwu.easydrop.data.connector.OfferPersistenceInterface;
|
||||
import de.rwu.easydrop.model.Offer;
|
||||
import de.rwu.easydrop.util.Config;
|
||||
|
||||
|
||||
class OfferRetrieverTest {
|
||||
|
||||
@Mock
|
||||
private Config config;
|
||||
@Mock
|
||||
private DataSourceFactory dataSourceFactory;
|
||||
@Mock
|
||||
private AmazonProductDataSource amazonDataSource;
|
||||
@Mock
|
||||
private EbayItemDataSource ebayDataSource;
|
||||
@Mock
|
||||
private OfferDTO offerDTO;
|
||||
@Mock
|
||||
private Offer offer;
|
||||
@Mock
|
||||
private OfferPersistenceInterface persistence;
|
||||
|
||||
private OfferRetriever offerRetriever;
|
||||
|
||||
@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);
|
||||
offerRetriever = new OfferRetriever(persistence);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getOfferFromPersistence(){
|
||||
|
||||
//Mock ProductDTO object to return from the offerDTO mock
|
||||
ProductDTO productDTO = mock(ProductDTO.class);
|
||||
when(productDTO.isAvailable()).thenReturn(true);
|
||||
|
||||
//Arrange
|
||||
String offerId = "187";
|
||||
String lastUpdate = "2023-01-01";
|
||||
when(persistence.getOfferDTOById(offerId)).thenReturn(offerDTO);
|
||||
when(offerDTO.getOfferId()).thenReturn(offerId);
|
||||
when(offerDTO.getLastUpdate()).thenReturn(lastUpdate);
|
||||
when(offerDTO.getSourceProduct()).thenReturn(productDTO);
|
||||
when(offerDTO.getTargetProduct()).thenReturn(productDTO);
|
||||
|
||||
//Act
|
||||
Offer result = offerRetriever.getOfferFromPersistence(offerId);
|
||||
|
||||
//Assert
|
||||
assertEquals(offerId, result.getOfferId());
|
||||
assertEquals(lastUpdate, result.getLastUpdate());
|
||||
|
||||
//Verify
|
||||
verify(persistence, times(1)).getOfferDTOById(offerId);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,6 +2,8 @@ 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.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
@@ -17,8 +19,9 @@ 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.data.connector.AbstractProductPersistence;
|
||||
import de.rwu.easydrop.data.connector.ProductPersistenceInterface;
|
||||
import de.rwu.easydrop.model.Product;
|
||||
import de.rwu.easydrop.model.Webshop;
|
||||
import de.rwu.easydrop.util.Config;
|
||||
|
||||
class ProductRetrieverTest {
|
||||
@@ -35,7 +38,7 @@ class ProductRetrieverTest {
|
||||
@Mock
|
||||
private Product product;
|
||||
@Mock
|
||||
private AbstractProductPersistence persistence;
|
||||
private ProductPersistenceInterface persistence;
|
||||
|
||||
private ProductRetriever productRetriever;
|
||||
|
||||
@@ -45,7 +48,7 @@ class ProductRetrieverTest {
|
||||
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);
|
||||
productRetriever = new ProductRetriever(dataSourceFactory, persistence);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -56,7 +59,7 @@ class ProductRetrieverTest {
|
||||
when(amazonDataSource.getProductDTOById(asin)).thenReturn(productDTO);
|
||||
when(productDTO.getProductId()).thenReturn(asin);
|
||||
when(productDTO.getCurrentPrice()).thenReturn(9.99);
|
||||
when(productDTO.getDataOrigin()).thenReturn("Amazon");
|
||||
when(productDTO.getDataOrigin()).thenReturn(Webshop.AMAZON);
|
||||
|
||||
// Act
|
||||
Product result = productRetriever.getProductFromAmazon(asin);
|
||||
@@ -76,7 +79,7 @@ class ProductRetrieverTest {
|
||||
when(ebayDataSource.getProductDTOById(productQuery)).thenReturn(productDTO);
|
||||
when(productDTO.getProductId()).thenReturn(productQuery);
|
||||
when(productDTO.getCurrentPrice()).thenReturn(9.99);
|
||||
when(productDTO.getDataOrigin()).thenReturn("eBay");
|
||||
when(productDTO.getDataOrigin()).thenReturn(Webshop.EBAY);
|
||||
|
||||
// Act
|
||||
Product result = productRetriever.getProductFromEbay(productQuery);
|
||||
@@ -92,11 +95,10 @@ class ProductRetrieverTest {
|
||||
void getProductFromPersistence_ValidProductId_ReturnsProduct() {
|
||||
// Arrange
|
||||
String productId = "123";
|
||||
when(dataSourceFactory.createProductPersistenceDataSource()).thenReturn(persistence);
|
||||
when(persistence.getProductDTOById(productId)).thenReturn(productDTO);
|
||||
when(productDTO.getProductId()).thenReturn(productId);
|
||||
when(productDTO.getCurrentPrice()).thenReturn(9.99);
|
||||
when(productDTO.getDataOrigin()).thenReturn("Amazon");
|
||||
when(productDTO.getDataOrigin()).thenReturn(Webshop.AMAZON);
|
||||
|
||||
// Act
|
||||
Product result = productRetriever.getProductFromPersistence(productId);
|
||||
@@ -108,4 +110,49 @@ class ProductRetrieverTest {
|
||||
// Verify the interactions
|
||||
verify(persistence, times(1)).getProductDTOById(productId);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getProductFromWebshop_ValidAmazonWebshop_ReturnsProduct() {
|
||||
// Arrange
|
||||
String productIdentifier = "ASIN1";
|
||||
ProductDTO dto = new ProductDTO(productIdentifier, Webshop.AMAZON);
|
||||
dto.setCurrentPrice(1.23);
|
||||
AmazonProductDataSource dataSource = mock(AmazonProductDataSource.class);
|
||||
Product expectedProduct = new Product();
|
||||
expectedProduct.setProductId(productIdentifier);
|
||||
expectedProduct.setDataOrigin(Webshop.AMAZON);
|
||||
expectedProduct.setCurrentPrice(1.23);
|
||||
when(dataSource.getProductDTOById(productIdentifier)).thenReturn(dto);
|
||||
when(dataSourceFactory.createAmazonProductDataSource()).thenReturn(dataSource);
|
||||
|
||||
// Act
|
||||
Product actualProduct = productRetriever.getProductFromWebshop(Webshop.AMAZON, productIdentifier);
|
||||
|
||||
// Assert
|
||||
assertEquals(expectedProduct, actualProduct);
|
||||
verify(dataSourceFactory).createAmazonProductDataSource();
|
||||
verify(dataSource).getProductDTOById(productIdentifier);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getProductFromWebshop_ValidEbayWebshop_ReturnsProduct() {
|
||||
// Arrange
|
||||
String productIdentifier = "ASIN1";
|
||||
ProductDTO dto = new ProductDTO(productIdentifier, Webshop.EBAY);
|
||||
dto.setCurrentPrice(1.23);
|
||||
Product expectedProduct = new Product();
|
||||
expectedProduct.setProductId(productIdentifier);
|
||||
expectedProduct.setDataOrigin(Webshop.EBAY);
|
||||
expectedProduct.setCurrentPrice(1.23);
|
||||
when(ebayDataSource.getProductDTOById(productIdentifier)).thenReturn(dto);
|
||||
when(dataSourceFactory.createEbayItemDataSource()).thenReturn(ebayDataSource);
|
||||
|
||||
// Act
|
||||
Product actualProduct = productRetriever.getProductFromWebshop(Webshop.EBAY, productIdentifier);
|
||||
|
||||
// Assert
|
||||
assertEquals(expectedProduct, actualProduct);
|
||||
verify(dataSourceFactory).createEbayItemDataSource();
|
||||
verify(ebayDataSource).getProductDTOById(productIdentifier);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
package de.rwu.easydrop.service.validation;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
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 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.InvalidOfferException;
|
||||
import de.rwu.easydrop.model.Offer;
|
||||
|
||||
class OfferValidatorTest {
|
||||
@Test
|
||||
void testConstructorIsPrivate()
|
||||
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
|
||||
// Check for private constructor
|
||||
Constructor<OfferValidator> constructor = OfferValidator.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_Offer_ValidProduct_NoExceptionThrown() {
|
||||
// Arrange
|
||||
Offer offer = new Offer();
|
||||
offer.setOfferId("3672");
|
||||
offer.setLastUpdate("2021-02-03");
|
||||
|
||||
// Act and Assert
|
||||
assertDoesNotThrow(() -> OfferValidator.validate(offer));
|
||||
}
|
||||
|
||||
@Test
|
||||
void validate_Offer_NullPointer() {
|
||||
// Arrange
|
||||
Offer offer = new Offer();
|
||||
|
||||
InvalidOfferException e = assertThrows(InvalidOfferException.class, () -> {
|
||||
OfferValidator.validate(offer);
|
||||
});
|
||||
|
||||
assertEquals("Required information is missing in the offer", e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("invalidOfferProvider")
|
||||
void validate_InvalidOffer_ThrowsInvalidOfferException(Offer offer) {
|
||||
// Act and Assert
|
||||
assertThrows(InvalidOfferException.class, () -> OfferValidator.validate(offer));
|
||||
|
||||
}
|
||||
|
||||
static Stream<Offer> invalidOfferProvider() {
|
||||
return Stream.of(
|
||||
createOfferWithEmptylastUpdate(),
|
||||
createOfferWithEmptyId());
|
||||
}
|
||||
|
||||
private static Offer createOfferWithEmptylastUpdate() {
|
||||
Offer offer = new Offer();
|
||||
offer.setOfferId("3729798");
|
||||
offer.setLastUpdate("");
|
||||
return offer;
|
||||
}
|
||||
|
||||
private static Offer createOfferWithEmptyId() {
|
||||
Offer offer = new Offer();
|
||||
offer.setOfferId("");
|
||||
offer.setLastUpdate("8798476");
|
||||
return offer;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
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;
|
||||
|
||||
@@ -16,6 +15,7 @@ import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import de.rwu.easydrop.exception.InvalidProductException;
|
||||
import de.rwu.easydrop.model.Product;
|
||||
import de.rwu.easydrop.model.Webshop;
|
||||
|
||||
class ProductValidatorTest {
|
||||
|
||||
@@ -38,37 +38,13 @@ class ProductValidatorTest {
|
||||
// Arrange
|
||||
Product product = new Product();
|
||||
product.setCurrentPrice(9.99);
|
||||
product.setDataOrigin("Amazon");
|
||||
product.setDataOrigin(Webshop.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) {
|
||||
@@ -79,22 +55,13 @@ class ProductValidatorTest {
|
||||
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.setDataOrigin(Webshop.AMAZON);
|
||||
product.setProductId("12345");
|
||||
return product;
|
||||
}
|
||||
@@ -102,7 +69,7 @@ class ProductValidatorTest {
|
||||
private static Product createProductWithEmptyProductId() {
|
||||
Product product = new Product();
|
||||
product.setCurrentPrice(9.99);
|
||||
product.setDataOrigin("Amazon");
|
||||
product.setDataOrigin(Webshop.AMAZON);
|
||||
product.setProductId("");
|
||||
return product;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
package de.rwu.easydrop.service.validation;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
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.exception.InvalidTransactionException;
|
||||
import de.rwu.easydrop.model.Transaction;
|
||||
|
||||
class TransactionValidatorTest {
|
||||
@Test
|
||||
void testConstructorIsPrivate()
|
||||
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
|
||||
// Check for private constructor
|
||||
Constructor<TransactionValidator> constructor = TransactionValidator.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_ValidTransaction_NoExceptionThrown() {
|
||||
// Arrange
|
||||
Transaction transaction = new Transaction();
|
||||
transaction.setOfferId("123");
|
||||
transaction.setVolume(123f);
|
||||
transaction.setEarnings(12.23);
|
||||
transaction.setTransactionTime("2020-01-01 00:00:00");
|
||||
|
||||
// Act & Assert
|
||||
assertDoesNotThrow(() -> TransactionValidator.validate(transaction));
|
||||
}
|
||||
|
||||
@Test
|
||||
void validate_InvalidTransaction_InvalidTransactionExceptionThrown() {
|
||||
// Arrange
|
||||
Transaction tx1 = new Transaction();
|
||||
tx1.setOfferId(""); // Set an empty Offer ID to make it invalid
|
||||
Transaction tx2 = new Transaction();
|
||||
tx2.setOfferId("123");
|
||||
Transaction tx3 = new Transaction();
|
||||
tx3.setOfferId("123");
|
||||
tx3.setEarnings(123f);
|
||||
|
||||
// Act & Assert
|
||||
assertThrows(InvalidTransactionException.class, () -> TransactionValidator.validate(tx1));
|
||||
assertThrows(InvalidTransactionException.class, () -> TransactionValidator.validate(tx2));
|
||||
assertThrows(InvalidTransactionException.class, () -> TransactionValidator.validate(tx3));
|
||||
}
|
||||
|
||||
@Test
|
||||
void validate_NullTransaction_InvalidTransactionExceptionThrown() {
|
||||
// Arrange
|
||||
Transaction transaction = null;
|
||||
|
||||
// Act & Assert
|
||||
assertThrows(InvalidTransactionException.class, () -> TransactionValidator.validate(transaction));
|
||||
}
|
||||
}
|
||||
@@ -13,14 +13,15 @@ import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import de.rwu.easydrop.api.dto.ProductDTO;
|
||||
import de.rwu.easydrop.data.connector.AbstractProductPersistence;
|
||||
import de.rwu.easydrop.data.connector.ProductPersistenceInterface;
|
||||
import de.rwu.easydrop.model.Product;
|
||||
import de.rwu.easydrop.model.ProductCatalogue;
|
||||
import de.rwu.easydrop.model.Webshop;
|
||||
|
||||
class CatalogueWriterTest {
|
||||
|
||||
@Mock
|
||||
private AbstractProductPersistence persistenceMock;
|
||||
private ProductPersistenceInterface persistenceMock;
|
||||
|
||||
private CatalogueWriter catalogueWriter;
|
||||
|
||||
@@ -39,19 +40,19 @@ class CatalogueWriterTest {
|
||||
catalogueWriter.writeCatalogues(catalogues);
|
||||
|
||||
// Assert
|
||||
verify(persistenceMock, times(4)).saveProduct(any(ProductDTO.class));
|
||||
verify(persistenceMock, times(4)).writeProduct(any(ProductDTO.class));
|
||||
}
|
||||
|
||||
private List<ProductCatalogue> createSampleCatalogues() {
|
||||
List<ProductCatalogue> catalogues = new ArrayList<>();
|
||||
|
||||
ProductCatalogue catalogue1 = new ProductCatalogue("Catalogue 1", "Sample catalogue 1");
|
||||
catalogue1.addProduct(createSampleProduct("Amazon", "ID 1"));
|
||||
catalogue1.addProduct(createSampleProduct("eBay", "ID 2"));
|
||||
catalogue1.addProduct(createSampleProduct(Webshop.AMAZON, "ID 1"));
|
||||
catalogue1.addProduct(createSampleProduct(Webshop.EBAY, "ID 2"));
|
||||
|
||||
ProductCatalogue catalogue2 = new ProductCatalogue("Catalogue 2", "Sample catalogue 2");
|
||||
catalogue2.addProduct(createSampleProduct("Amazon", "ID 3"));
|
||||
catalogue2.addProduct(createSampleProduct("eBay", "ID 4"));
|
||||
catalogue2.addProduct(createSampleProduct(Webshop.AMAZON, "ID 3"));
|
||||
catalogue2.addProduct(createSampleProduct(Webshop.EBAY, "ID 4"));
|
||||
|
||||
catalogues.add(catalogue1);
|
||||
catalogues.add(catalogue2);
|
||||
@@ -59,7 +60,7 @@ class CatalogueWriterTest {
|
||||
return catalogues;
|
||||
}
|
||||
|
||||
private Product createSampleProduct(String dataOrigin, String productId) {
|
||||
private Product createSampleProduct(Webshop dataOrigin, String productId) {
|
||||
Product product = new Product();
|
||||
product.setDataOrigin(dataOrigin);
|
||||
product.setProductId(productId);
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
package de.rwu.easydrop.service.writer;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import de.rwu.easydrop.api.dto.OfferDTO;
|
||||
import de.rwu.easydrop.data.connector.OfferPersistenceInterface;
|
||||
import de.rwu.easydrop.model.Offer;
|
||||
import de.rwu.easydrop.model.Product;
|
||||
import de.rwu.easydrop.model.Webshop;
|
||||
|
||||
class OfferWriterTest {
|
||||
|
||||
@Mock
|
||||
private OfferDTO offerDTO;
|
||||
@Mock
|
||||
private OfferPersistenceInterface persistence;
|
||||
|
||||
private OfferWriter offerWriter;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
MockitoAnnotations.openMocks(this);
|
||||
offerWriter = new OfferWriter(persistence);
|
||||
}
|
||||
|
||||
@Test
|
||||
void writeOfferToPersistence_InvalidProduct_ThrowsException() {
|
||||
//Arrange
|
||||
Offer offer = new Offer();
|
||||
offer.setOfferId("");
|
||||
offer.setLastUpdate("");
|
||||
|
||||
//Act and Assert
|
||||
assertThrows(Exception.class, () -> offerWriter.writeOfferToPersistence(offer));
|
||||
}
|
||||
|
||||
@Test
|
||||
void writeOfferToPresistence_ValidProduct_CallsSaveProduct(){
|
||||
|
||||
// Arrange
|
||||
Product product = new Product();
|
||||
product.setProductId("12345");
|
||||
product.setDataOrigin(Webshop.AMAZON);
|
||||
product.setCurrentPrice(9.99);
|
||||
|
||||
// Arrange
|
||||
Offer offer = new Offer();
|
||||
offer.setOfferId("26876");
|
||||
offer.setLastUpdate("2022-12-25");
|
||||
offer.setSourceProduct(product);
|
||||
offer.setTargetProduct(product);
|
||||
|
||||
// Act
|
||||
offerWriter.writeOfferToPersistence(offer);
|
||||
|
||||
// Assert
|
||||
Mockito.verify(persistence).writeOffer(any(OfferDTO.class));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -10,21 +10,21 @@ import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import de.rwu.easydrop.api.dto.ProductDTO;
|
||||
import de.rwu.easydrop.data.connector.AbstractProductPersistence;
|
||||
import de.rwu.easydrop.data.connector.ProductPersistenceInterface;
|
||||
import de.rwu.easydrop.model.Product;
|
||||
import de.rwu.easydrop.model.Webshop;
|
||||
|
||||
class ProductWriterTest {
|
||||
|
||||
@Mock
|
||||
private AbstractProductPersistence persistence;
|
||||
private ProductPersistenceInterface persistence;
|
||||
|
||||
private ProductWriter productWriter;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
MockitoAnnotations.openMocks(this);
|
||||
productWriter = new ProductWriter();
|
||||
productWriter.setPersistence(persistence);
|
||||
productWriter = new ProductWriter(persistence);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -32,14 +32,14 @@ class ProductWriterTest {
|
||||
// Arrange
|
||||
Product product = new Product();
|
||||
product.setProductId("12345");
|
||||
product.setDataOrigin("Amazon");
|
||||
product.setDataOrigin(Webshop.AMAZON);
|
||||
product.setCurrentPrice(9.99);
|
||||
|
||||
// Act
|
||||
productWriter.writeProductToPersistence(product);
|
||||
|
||||
// Assert
|
||||
Mockito.verify(persistence).saveProduct(any(ProductDTO.class));
|
||||
Mockito.verify(persistence).writeProduct(any(ProductDTO.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -47,7 +47,7 @@ class ProductWriterTest {
|
||||
// Arrange
|
||||
Product product = new Product();
|
||||
product.setProductId("");
|
||||
product.setDataOrigin("Amazon");
|
||||
product.setDataOrigin(Webshop.AMAZON);
|
||||
|
||||
// Act and Assert
|
||||
assertThrows(Exception.class, () -> productWriter.writeProductToPersistence(product));
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package de.rwu.easydrop.service.writer;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
|
||||
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.dto.TransactionDTO;
|
||||
import de.rwu.easydrop.data.connector.TransactionPersistenceInterface;
|
||||
import de.rwu.easydrop.exception.InvalidTransactionException;
|
||||
import de.rwu.easydrop.model.Transaction;
|
||||
import de.rwu.easydrop.service.mapping.TransactionMapper;
|
||||
|
||||
class TransactionWriterTest {
|
||||
|
||||
@Mock
|
||||
private TransactionPersistenceInterface persistence;
|
||||
|
||||
private TransactionWriter writer;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
MockitoAnnotations.openMocks(this);
|
||||
writer = new TransactionWriter(persistence);
|
||||
}
|
||||
|
||||
@Test
|
||||
void writeTXToPersistence_ValidTransaction_TransactionSaved() {
|
||||
// Arrange
|
||||
Transaction transaction = new Transaction();
|
||||
transaction.setOfferId("123");
|
||||
transaction.setVolume(123f);
|
||||
transaction.setEarnings(12.23);
|
||||
transaction.setTransactionTime("2020-01-01 00:00:00");
|
||||
|
||||
TransactionDTO expectedDTO = TransactionMapper.mapTXToDTO(transaction);
|
||||
|
||||
// Act
|
||||
writer.writeTXToPersistence(transaction);
|
||||
|
||||
// Assert
|
||||
verify(persistence).writeTX(expectedDTO);
|
||||
}
|
||||
|
||||
@Test
|
||||
void writeTXToPersistence_InvalidTransaction_ValidationExceptionThrown() {
|
||||
// Arrange
|
||||
Transaction transaction = new Transaction();
|
||||
transaction.setVolume(123f);
|
||||
transaction.setEarnings(12.23);
|
||||
transaction.setTransactionTime("2020-01-01 00:00:00");
|
||||
|
||||
// Act & Assert
|
||||
assertThrows(InvalidTransactionException.class, () -> writer.writeTXToPersistence(transaction));
|
||||
|
||||
// Verify that persistence.writeTX is not called
|
||||
verifyNoInteractions(persistence);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package de.rwu.easydrop.util;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@@ -55,4 +56,17 @@ class FormattingUtilTest {
|
||||
|
||||
Assertions.assertEquals(expectedFormattedAmount, formattedAmount);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRemoveSpaces_RemovesAllSpaces() {
|
||||
String test1 = FormattingUtil.removeSpaces("this is a test");
|
||||
String test2 = FormattingUtil.removeSpaces("another test");
|
||||
String test3 = FormattingUtil.removeSpaces(" daring today, aren't we? ");
|
||||
String test4 = FormattingUtil.removeSpaces("hehe");
|
||||
|
||||
assertEquals("thisisatest", test1);
|
||||
assertEquals("anothertest", test2);
|
||||
assertEquals("daringtoday,aren'twe?", test3);
|
||||
assertEquals("hehe", test4);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
description: "Integration Testing Product",
|
||||
"identifiers": [
|
||||
{
|
||||
"Amazon": "DEMO-AMAZON-001"
|
||||
"AMAZON": "DEMO-AMAZON-001"
|
||||
},
|
||||
{
|
||||
"eBay": "DEMO-EBAY-001"
|
||||
"EBAY": "DEMO-EBAY-001"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
"description": "Integration Testing Product",
|
||||
"identifiers": [
|
||||
{
|
||||
"Amazon": "DEMO-AMAZON-001"
|
||||
"AMAZON": "DEMO-AMAZON-001"
|
||||
},
|
||||
{
|
||||
"eBay": "DEMO-EBAY-001"
|
||||
"EBAY": "DEMO-EBAY-001"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user