Merge branch '#53-Data-Persistence' into 'dev'

Data Persistence Implementation

See merge request team1/sandbox2!5
This commit is contained in:
Marvin Scham
2023-06-07 21:24:53 +00:00
44 changed files with 1524 additions and 46 deletions

2
.gitignore vendored
View File

@@ -3,6 +3,8 @@
###################################################################################################
config.properties
products-config.json
persistence.db
###################################################################################################
## Visual Studio Code #############################################################################

View File

@@ -5,13 +5,14 @@
### Added
- `EbayItemDataSource` (#37)
- Product data persistence via SQLite integration (#53)
- Mutation testing capabilities via PITest (#66)
- `Product` class
- Mapping between Product and its corresponding DTO
- Dependencies: Lombok for easier notation, JUnit 5 Params for repetitive tests
- Product Validation
- Product Retrieval
- Unit Tests
- Product validation, retrieval and persistence writing
- Product catalogue retrieval and persistence writing
- More unit tests
### Changed

View File

@@ -3,3 +3,5 @@ mvn clean verify sonar:sonar -Pcoverage \
-Dsonar.projectName='EasyDrop' \
-Dsonar.host.url=http://localhost:9000 \
-Dsonar.token=sqp_82d35689c620c15fd1064549375e17a2a5b0b931
start http://localhost:9000/dashboard?id=EasyDrop

View File

@@ -0,0 +1,16 @@
{
"products": [
{
"name": "Gigabyte GeForce RTX 3060",
"description": "Very epic GPU",
"identifiers": [
{
"Amazon": "B096Y2TYKV"
},
{
"eBay": "Gigabyte GeForce RTX 3060"
}
]
}
]
}

View File

@@ -76,6 +76,12 @@
<artifactId>logback-classic</artifactId>
<version>1.4.7</version>
</dependency>
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.42.0.0</version>
</dependency>
</dependencies>
<build>

View File

@@ -1,13 +1,22 @@
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.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;
/**
* Kickoff point for the service.
@@ -34,12 +43,20 @@ public final class Main {
*/
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);
String amznProduct = retriever.getProductFromAmazon("B096Y2TYKV").toString();
LOGGER.info(amznProduct);
String ebayProduct = retriever.getProductFromEbay("Gigabyte GeForce RTX 3060").toString();
LOGGER.info(ebayProduct);
catRetriever.loadCatalogues();
List<ProductCatalogue> pCats = catRetriever.getProductCatalogues();
catWriter.writeCatalogues(pCats);
for (ProductCatalogue pCat : pCats) {
String pCatStr = pCat.toString();
LOGGER.info(pCatStr);
}
}
}

View File

@@ -2,6 +2,8 @@ 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;
/**
@@ -15,6 +17,17 @@ 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
@@ -52,4 +65,17 @@ 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;
}
}

View File

@@ -0,0 +1,34 @@
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();
}

View File

@@ -1,10 +0,0 @@
package de.rwu.easydrop.data.connector;
/**
* Allows connecting to a SQLite Database.
*
* TODO implement
*/
public class DatabaseConnector {
}

View File

@@ -0,0 +1,173 @@
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 org.sqlite.SQLiteDataSource;
import de.rwu.easydrop.api.dto.ProductDTO;
import de.rwu.easydrop.exception.PersistenceException;
/**
* Allows connecting to a SQLite Database.
*
* @since 0.2.0
*/
public final class SQLiteConnector extends AbstractProductPersistence {
/**
* Data origin.
*/
private static final String DATA_ORIGIN = "SQLite";
/**
* SQLite Database.
*/
private SQLiteDataSource db;
/**
* @param src the db to set
*/
public void setDb(final SQLiteDataSource src) {
this.db = src;
}
/**
* Path to SQLite db file.
*/
private static final String PERSISTENCE_PATH = "jdbc:sqlite:persistence.db";
/**
* Creates instance.
*
* @param src SQLite Data Source
*/
public SQLiteConnector(final SQLiteDataSource src) {
db = src;
db.setUrl(PERSISTENCE_PATH);
initializeDatabase();
}
private void initializeDatabase() {
try {
// Create a new database connection
Connection connection = db.getConnection();
// Execute SQL statements to create tables
Statement statement = connection.createStatement();
statement.execute(
"CREATE TABLE IF NOT EXISTS products ("
+ "dataOrigin TEXT, "
+ "productId TEXT, "
+ "currentPrice REAL, "
+ "merchant TEXT, "
+ "deliveryPrice REAL, "
+ "available INT, "
+ "lastupdate TEXT, "
+ "UNIQUE(productId, dataOrigin) ON CONFLICT REPLACE"
+ ")");
// Close the statement and connection
statement.close();
connection.close();
} catch (SQLException e) {
throw new PersistenceException("Something went wrong while initializing SQLite DB", e);
}
}
/**
* Writes a ProductDTO to persistence.
*
* @param dto
*/
public void saveProduct(final ProductDTO dto) {
String query = "INSERT INTO products ("
+ "dataOrigin, productId, currentPrice, merchant, "
+ "deliveryPrice, available, lastupdate"
+ ") VALUES ("
+ "?, ?, ?, ?, ?, ?, datetime('now', 'localtime')"
+ ")";
try (Connection connection = db.getConnection();
PreparedStatement statement = connection.prepareStatement(query)) {
int index = 0;
statement.setString(++index, dto.getDataOrigin());
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.executeUpdate();
} catch (SQLException e) {
throw new PersistenceException("Something went wrong while saving to SQLite", e);
}
}
@Override
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)) {
statement.setString(1, productId);
try (ResultSet resultSet = statement.executeQuery()) {
if (resultSet.next()) {
dto = new ProductDTO(resultSet.getString("productId"),
resultSet.getString("dataOrigin"));
dto.setCurrentPrice(resultSet.getDouble("currentPrice"));
dto.setMerchant(resultSet.getString("merchant"));
dto.setDeliveryPrice(resultSet.getDouble("deliveryPrice"));
dto.setAvailable(resultSet.getBoolean("available"));
}
}
} catch (SQLException e) {
throw new PersistenceException("Something went wrong while reading from SQLite", e);
}
return dto;
}
/**
* Deletes all data from persistence.
*/
public void clearData() {
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);
}
}
@Override
protected String getDataOrigin() {
return DATA_ORIGIN;
}
@Override
protected String getApiKey() {
throw new UnsupportedOperationException(
this.getClass().getName() + " doesn't support getApiKey");
}
@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");
}
}

View File

@@ -1,6 +1,6 @@
/**
* Connectors for databases.
*
* TODO implement
* @since 0.2.0
*/
package de.rwu.easydrop.data.connector;

View File

@@ -1,10 +0,0 @@
package de.rwu.easydrop.data.dao;
/**
* Product data access object.
*
* TODO implement
*/
public class ProductDAO {
}

View File

@@ -1,6 +0,0 @@
/**
* Data access objects for business objects created from persistence.
*
* TODO implement
*/
package de.rwu.easydrop.data.dao;

View File

@@ -1,6 +1,6 @@
/**
* Structure for business objects and persisting their info.
*
* TODO implement
* @since 0.2.0
*/
package de.rwu.easydrop.data;

View File

@@ -0,0 +1,27 @@
package de.rwu.easydrop.exception;
/**
* Exception that signifies a problem with data persistence.
*
* @since 0.2.0
*/
public class PersistenceException extends RuntimeException {
/**
* Throws an exception that signifies the data of a Product are invalid.
*
* @param message
*/
public PersistenceException(final String message) {
super(message);
}
/**
* Throws an exception that signifies the data of a Product are invalid.
*
* @param message
* @param cause
*/
public PersistenceException(final String message, final Throwable cause) {
super(message, cause);
}
}

View File

@@ -0,0 +1,79 @@
package de.rwu.easydrop.model;
import java.util.ArrayList;
import java.util.List;
import lombok.Data;
/**
* Holds Product instances for one product from different data sources.
*
* @since 0.2.0
*/
@Data
public class ProductCatalogue {
/**
* Product name.
*/
private String productName;
/**
* Product description.
*/
private String description;
/**
* Product collection.
*/
private List<Product> products;
/**
* Creates new Product Catalogue.
*
* @param newProductName
* @param newDescription
*/
public ProductCatalogue(final String newProductName, final String newDescription) {
this.productName = newProductName;
this.description = newDescription;
this.products = new ArrayList<>();
}
/**
* Adds a product to the catalogue.
*
* @param product
*/
public void addProduct(final Product product) {
products.add(product);
}
/**
* Removes a product from the catalogue.
*
* @param product
*/
public void removeProduct(final Product product) {
products.remove(product);
}
/**
* Removes all products from the catalogue.
*/
public void clearProducts() {
products = new ArrayList<>();
}
/**
* Outputs the catalogue as a string.
*/
@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("Products:\n");
for (Product product : products) {
sb.append(product.toString()).append("\n");
}
return sb.toString();
}
}

View File

@@ -1,16 +1,17 @@
package de.rwu.easydrop.service.mapping;
import de.rwu.easydrop.api.dto.ProductDTO;
import de.rwu.easydrop.model.Product;
/**
* Maps between Product, ProductDAO and ProductDTO.
* Maps between Product, ProductDTO and ProductDTO.
*
* @since 0.2.0
*
* @see Product
* @see ProductDTO
* @see ProductDAO
* @see ProductDTO
*/
public final class ProductMapper {
@@ -41,4 +42,21 @@ public final class ProductMapper {
return product;
}
/**
* Creates a ProductDTO object from a corresponding Product.
*
* @param product Product
* @return ProductDTO
*/
public static ProductDTO mapProductToDTO(final Product product) {
ProductDTO dto = new ProductDTO(product.getProductId(), product.getDataOrigin());
dto.setAvailable(product.isAvailable());
dto.setCurrentPrice(product.getCurrentPrice());
dto.setDeliveryPrice(product.getDeliveryPrice());
dto.setMerchant(product.getMerchant());
return dto;
}
}

View File

@@ -1,6 +1,6 @@
/**
* Packages for supporting business logic.
*
* TODO implement
* @since 0.2.0
*/
package de.rwu.easydrop.service;

View File

@@ -1,6 +1,6 @@
/**
* Supports diverse business processes and enforces business rules.
*
* TODO implement
* @since 0.2.0
*/
package de.rwu.easydrop.service.processing;

View File

@@ -0,0 +1,78 @@
package de.rwu.easydrop.service.retriever;
import java.util.ArrayList;
import java.util.List;
import javax.naming.ConfigurationException;
import de.rwu.easydrop.exception.InvalidProductException;
import de.rwu.easydrop.model.Product;
import de.rwu.easydrop.model.ProductCatalogue;
import de.rwu.easydrop.util.ProductsConfig;
import lombok.Data;
/**
* Retrieves data for all products of multiple catalogues.
*
* @since 0.2.0
*/
@Data
public class CatalogueRetriever {
/**
* User-configured products.
*/
private ProductsConfig productsConfig;
/**
* Product Retriever.
*/
private ProductRetriever productRetriever;
/**
* Product catalogue.
*/
private List<ProductCatalogue> productCatalogues;
/**
* Creates a new instance.
*
* @param newProductsConfig
* @param newProductRetriever
*/
public CatalogueRetriever(
final ProductsConfig newProductsConfig, final ProductRetriever newProductRetriever) {
productRetriever = newProductRetriever;
productsConfig = newProductsConfig;
productCatalogues = new ArrayList<>();
}
/**
* Loads catalogues as configured by the user.
*
* @throws ConfigurationException
*/
public void loadCatalogues() throws ConfigurationException {
productsConfig.loadConfig();
for (ProductCatalogue pCat : productsConfig.getProductCatalogues()) {
ProductCatalogue newProductCatalogue = new ProductCatalogue(
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");
}
newProductCatalogue.addProduct(newProduct);
}
productCatalogues.add(newProductCatalogue);
}
}
}

View File

@@ -4,6 +4,7 @@ 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.model.Product;
import de.rwu.easydrop.service.mapping.ProductMapper;
import de.rwu.easydrop.service.validation.ProductValidator;
@@ -64,4 +65,20 @@ public class ProductRetriever {
return product;
}
/**
* Retrieves a product from persistence.
*
* @param productId
* @return Product from persistence
*/
public Product getProductFromPersistence(final String productId) {
AbstractProductPersistence src = dataSourceFactory.createProductPersistenceDataSource();
ProductDTO dto = src.getProductDTOById(productId);
Product product = ProductMapper.mapProductFromDTO(dto);
ProductValidator.validate(product);
return product;
}
}

View File

@@ -0,0 +1,47 @@
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.model.Product;
import de.rwu.easydrop.model.ProductCatalogue;
import de.rwu.easydrop.service.mapping.ProductMapper;
import de.rwu.easydrop.service.validation.ProductValidator;
/**
* Writes data for all products of multiple catalogues to persistence.
*
* @since 0.2.0
*/
public final class CatalogueWriter {
/**
* Holds a persistence reference.
*/
private AbstractProductPersistence persistence;
/**
* Creates new instance.
*
* @param newPersistence
*/
public CatalogueWriter(final AbstractProductPersistence newPersistence) {
persistence = newPersistence;
}
/**
* Writes all products of specified catalogues to persistence.
*
* @param catalogues
*/
public void writeCatalogues(final List<ProductCatalogue> catalogues) {
for (ProductCatalogue pCat : catalogues) {
for (Product product : pCat.getProducts()) {
ProductValidator.validate(product);
ProductDTO dto = ProductMapper.mapProductToDTO(product);
persistence.saveProduct(dto);
}
}
}
}

View File

@@ -0,0 +1,38 @@
package de.rwu.easydrop.service.writer;
import de.rwu.easydrop.api.dto.ProductDTO;
import de.rwu.easydrop.data.connector.AbstractProductPersistence;
import de.rwu.easydrop.model.Product;
import de.rwu.easydrop.service.mapping.ProductMapper;
import de.rwu.easydrop.service.validation.ProductValidator;
/**
* Wrapper for writing product info to persistence.
*
* @since 0.2.0
*/
public class ProductWriter {
/**
* Persistence.
*/
private AbstractProductPersistence persistence;
/**
* @param newPersistence the persistence to set
*/
public void setPersistence(final AbstractProductPersistence newPersistence) {
this.persistence = newPersistence;
}
/**
* Validates and saves product to persistence.
*
* @param product
*/
public void writeProductToPersistence(final Product product) {
ProductValidator.validate(product);
ProductDTO dto = ProductMapper.mapProductToDTO(product);
persistence.saveProduct(dto);
}
}

View File

@@ -0,0 +1,6 @@
/**
* Writes Objects to a data store.
*
* @since 0.2.0
*/
package de.rwu.easydrop.service.writer;

View File

@@ -52,7 +52,6 @@ public final class Config {
* Returns current config instance.
*
* @return Config instance
* @throws ConfigurationException
*/
public static Config getInstance() {
if (instance == null) {

View File

@@ -0,0 +1,142 @@
package de.rwu.easydrop.util;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javax.naming.ConfigurationException;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.JsonPathException;
import de.rwu.easydrop.model.Product;
import de.rwu.easydrop.model.ProductCatalogue;
/**
* Reads the user-specified catalogue of products.
*
* @since 0.2.0
*/
public final class ProductsConfig {
/**
* Products config location.
*/
private String configLocation = "config/products-config.json";
/**
* @return the configLocation
*/
public String getConfigLocation() {
return configLocation;
}
/**
* @param newConfigLocation the configLocation to set
*/
public void setConfigLocation(final String newConfigLocation) {
this.configLocation = newConfigLocation;
}
/**
* Holds the configured products.
*/
private List<ProductCatalogue> productCatalogues;
/**
* @return the product catalogues
*/
public List<ProductCatalogue> getProductCatalogues() {
return productCatalogues;
}
/**
* Singleton instance.
*/
private static ProductsConfig instance = null;
/**
* Private constructor to prevent external instantiation.
*/
private ProductsConfig() {
productCatalogues = new ArrayList<>();
}
/**
* Returns current products config instance.
*
* @return Products Config instance
*/
public static ProductsConfig getInstance() {
if (instance == null) {
instance = new ProductsConfig();
}
return instance;
}
/**
* Loads user-specified configuration into productCatalogues attribute.
*
* @throws ConfigurationException
*/
public void loadConfig() throws ConfigurationException {
try {
File jsonFile = new File(configLocation).getAbsoluteFile();
ArrayList<HashMap<String, Object>> jsonProducts = JsonPath.read(jsonFile, "$.products");
setProductCatalogues(jsonProducts);
} catch (IOException e) {
throw new ConfigurationException("Couldn't load required products config file");
} catch (JsonPathException e) {
throw new ConfigurationException("Products config is empty or malformed");
}
}
/**
* Loads catalogues from JSON.
*
* @param jsonCatalogues
*/
private void setProductCatalogues(final ArrayList<HashMap<String, Object>> jsonCatalogues) {
for (HashMap<String, Object> productCatalogue : jsonCatalogues) {
String name = productCatalogue.get("name").toString();
String desc = productCatalogue.get("description").toString();
String identifiers = productCatalogue.get("identifiers").toString();
ProductCatalogue pCat = new ProductCatalogue(name, desc);
addProductsToCatalogue(identifiers, pCat);
productCatalogues.add(pCat);
}
}
/**
* Loads products from JSON.
*
* @param jsonIdentifiers
* @param pCat
*/
private void addProductsToCatalogue(final String jsonIdentifiers, final ProductCatalogue pCat) {
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();
Product newProduct = new Product();
newProduct.setDataOrigin(dataOrigin);
newProduct.setProductId(identifier);
pCat.addProduct(newProduct);
}
}
/**
* Resets the contained product catalogues.
*/
public void reset() {
productCatalogues = new ArrayList<>();
}
}

View File

@@ -1,6 +1,6 @@
/**
* General utility such as formatting helpers.
*
* TODO implement
* @since 0.1.0
*/
package de.rwu.easydrop.util;

View File

@@ -1,6 +1,8 @@
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;
@@ -9,7 +11,10 @@ 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 {
@@ -45,4 +50,20 @@ class DataSourceFactoryTest {
// 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());
}
}

View File

@@ -0,0 +1,195 @@
package de.rwu.easydrop.data.connector;
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.assertNull;
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 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.ProductDTO;
import de.rwu.easydrop.exception.PersistenceException;
@TestInstance(Lifecycle.PER_CLASS)
class SQLiteConnectorTest {
private static final String TEST_PRODUCT_ID = "12345";
private SQLiteConnector sqliteConnector;
@Mock
private SQLiteDataSource mockDataSource;
@BeforeAll
public void setup() {
sqliteConnector = new SQLiteConnector(new SQLiteDataSource());
}
@BeforeEach
public void clearDatabase() {
MockitoAnnotations.openMocks(this);
}
@Test
void saveProduct_ValidProduct_SuccessfullySaved() {
// Arrange
sqliteConnector.clearData();
ProductDTO ProductDTO = new ProductDTO(TEST_PRODUCT_ID, "Amazon");
ProductDTO.setDataOrigin("Amazon");
ProductDTO.setProductId(TEST_PRODUCT_ID);
ProductDTO.setCurrentPrice(9.99);
ProductDTO.setMerchant("Sample Merchant");
ProductDTO.setDeliveryPrice(2.50);
ProductDTO.setAvailable(true);
// Act
assertDoesNotThrow(() -> sqliteConnector.saveProduct(ProductDTO));
// Assert
ProductDTO savedProductDTO = sqliteConnector.getProductDTOById(TEST_PRODUCT_ID);
assertNotNull(savedProductDTO);
assertEquals("Amazon", savedProductDTO.getDataOrigin());
assertEquals(TEST_PRODUCT_ID, savedProductDTO.getProductId());
assertEquals(9.99, savedProductDTO.getCurrentPrice());
assertEquals("Sample Merchant", savedProductDTO.getMerchant());
assertEquals(2.50, savedProductDTO.getDeliveryPrice());
assertTrue(savedProductDTO.isAvailable());
}
@Test
void getProductDTOById_ProductExists_ReturnsProductDTO() {
// Arrange
sqliteConnector.clearData();
insertSampleProduct();
// Act
ProductDTO ProductDTO = sqliteConnector.getProductDTOById(TEST_PRODUCT_ID);
// Assert
assertNotNull(ProductDTO);
assertEquals("Amazon", ProductDTO.getDataOrigin());
assertEquals(TEST_PRODUCT_ID, ProductDTO.getProductId());
assertEquals(9.99, ProductDTO.getCurrentPrice());
assertEquals("Sample Merchant", ProductDTO.getMerchant());
assertEquals(2.50, ProductDTO.getDeliveryPrice());
assertTrue(ProductDTO.isAvailable());
}
@Test
void constructor_ThrowsPersistenceException_OnSQLException() {
try {
doThrow(SQLException.class).when(mockDataSource).getConnection();
PersistenceException exception = assertThrows(PersistenceException.class, () -> {
new SQLiteConnector(mockDataSource);
});
assertEquals("Something went wrong while initializing SQLite DB", exception.getMessage());
} catch (SQLException e) {
fail("No SQLException should be thrown");
}
}
@Test
void getProductDTOById_ProductDoesNotExist_ReturnsNull() {
// Act
ProductDTO ProductDTO = sqliteConnector.getProductDTOById("FAKE_ID");
// Assert
assertNull(ProductDTO);
}
@Test
void saveProduct_ThrowsPersistenceException_OnSQLException() throws SQLException {
// Arrange
ProductDTO ProductDTO = new ProductDTO(TEST_PRODUCT_ID, "Amazon");
sqliteConnector.setDb(mockDataSource);
doThrow(SQLException.class).when(mockDataSource).getConnection();
// Act and Assert
assertThrows(PersistenceException.class, () -> sqliteConnector.saveProduct(ProductDTO));
}
@Test
void getProductDTOById_ThrowsPersistenceException_OnSQLException() throws SQLException {
// Arrange
String productId = "12345";
sqliteConnector.setDb(mockDataSource);
doThrow(SQLException.class).when(mockDataSource).getConnection();
// Act and Assert
assertThrows(PersistenceException.class, () -> sqliteConnector.getProductDTOById(productId));
}
@Test
void clearData_ThrowsPersistenceException_OnSQLException() throws SQLException {
// Arrange
sqliteConnector.setDb(mockDataSource);
doThrow(SQLException.class).when(mockDataSource).getConnection();
// Act and Assert
assertThrows(PersistenceException.class, () -> sqliteConnector.clearData());
}
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);
}
@Test
void getDataOrigin_ReturnsCorrectDataOrigin() {
// Arrange
SQLiteConnector connector = new SQLiteConnector(new SQLiteDataSource());
// Act
String dataOrigin = connector.getDataOrigin();
// Assert
assertEquals("SQLite", dataOrigin);
}
@Test
void getApiKey_UnsupportedOperationExceptionThrown() {
// Arrange
SQLiteConnector connector = new SQLiteConnector(new SQLiteDataSource());
// Act and Assert
assertThrows(UnsupportedOperationException.class, connector::getApiKey);
}
@Test
void buildProductDTO_UnsupportedOperationExceptionThrown() {
// Arrange
SQLiteConnector connector = new SQLiteConnector(new SQLiteDataSource());
ProductDTO product = new ProductDTO("ASIN123", "Amazon");
String json = "{\"productId\":\"ASIN123\",\"dataOrigin\":\"Amazon\"}";
// Act and Assert
assertThrows(UnsupportedOperationException.class, () -> connector.buildProductDTO(product, json));
}
@Test
void createApiUrl_UnsupportedOperationExceptionThrown() {
// Arrange
SQLiteConnector connector = new SQLiteConnector(new SQLiteDataSource());
String productIdentifier = "ASIN123";
// Act and Assert
assertThrows(UnsupportedOperationException.class, () -> connector.createApiUrl(productIdentifier));
}
}

View File

@@ -0,0 +1,28 @@
package de.rwu.easydrop.exception;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import org.junit.jupiter.api.Test;
class PersistenceExceptionTest {
@Test
void testPersistenceExceptionWithMessage() {
String errorMessage = "Error occurred during data persistence.";
PersistenceException exception = new PersistenceException(errorMessage);
assertEquals(errorMessage, exception.getMessage());
assertNull(exception.getCause());
}
@Test
void testPersistenceExceptionWithMessageAndCause() {
String errorMessage = "Error occurred during data persistence.";
Throwable cause = new IllegalArgumentException("Invalid argument.");
PersistenceException exception = new PersistenceException(errorMessage, cause);
assertEquals(errorMessage, exception.getMessage());
assertEquals(cause, exception.getCause());
}
}

View File

@@ -0,0 +1,93 @@
package de.rwu.easydrop.model;
import java.util.List;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class ProductCatalogueTest {
private ProductCatalogue productCatalogue;
@BeforeEach
public void setup() {
productCatalogue = new ProductCatalogue("GPU", "Graphics Processing Units");
}
@Test
void testAddProduct() {
Product product = new Product();
product.setProductId("12345");
product.setMerchant("AmazonSeller");
product.setDataOrigin("Amazon");
productCatalogue.addProduct(product);
List<Product> products = productCatalogue.getProducts();
Assertions.assertEquals(1, products.size());
Assertions.assertEquals(product, products.get(0));
}
@Test
void testRemoveProduct() {
Product product1 = new Product();
product1.setProductId("12345");
product1.setMerchant("AmazonSeller");
product1.setDataOrigin("Amazon");
productCatalogue.addProduct(product1);
Product product2 = new Product();
product2.setProductId("54321");
product2.setMerchant("eBaySeller");
product2.setDataOrigin("eBay");
productCatalogue.addProduct(product2);
productCatalogue.removeProduct(product1);
List<Product> products = productCatalogue.getProducts();
Assertions.assertEquals(1, products.size());
Assertions.assertEquals(product2, products.get(0));
}
@Test
void testClearProducts() {
Product product1 = new Product();
product1.setProductId("12345");
product1.setMerchant("AmazonSeller");
product1.setDataOrigin("Amazon");
productCatalogue.addProduct(product1);
Product product2 = new Product();
product2.setProductId("54321");
product2.setMerchant("eBay");
product2.setDataOrigin("eBay");
productCatalogue.addProduct(product2);
productCatalogue.clearProducts();
List<Product> products = productCatalogue.getProducts();
Assertions.assertTrue(products.isEmpty());
}
@Test
void testToString() {
Product product1 = new Product();
product1.setProductId("12345");
product1.setMerchant("AmazonSeller");
product1.setDataOrigin("Amazon");
productCatalogue.addProduct(product1);
Product product2 = new Product();
product2.setProductId("54321");
product2.setMerchant("eBaySeller");
product2.setDataOrigin("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 € (available: no)]\n" +
"Product: [54321 from eBaySeller (eBay) at 0,00 € (available: no)]\n";
Assertions.assertEquals(expectedString, productCatalogue.toString());
}
}

View File

@@ -11,6 +11,7 @@ import java.lang.reflect.Modifier;
import org.junit.jupiter.api.Test;
import de.rwu.easydrop.api.dto.ProductDTO;
import de.rwu.easydrop.model.Product;
class ProductMapperTest {
@@ -53,4 +54,27 @@ class ProductMapperTest {
dto.setMerchant("Example Merchant");
return dto;
}
@Test
void mapProductToDTO() {
// Arrange
Product product = new Product();
product.setProductId("12345");
product.setDataOrigin("Amazon");
product.setAvailable(true);
product.setCurrentPrice(9.99);
product.setDeliveryPrice(2.50);
product.setMerchant("Seller1");
// Act
ProductDTO dto = ProductMapper.mapProductToDTO(product);
// Assert
assertEquals("12345", dto.getProductId());
assertEquals("Amazon", dto.getDataOrigin());
assertTrue(dto.isAvailable());
assertEquals(9.99, dto.getCurrentPrice());
assertEquals(2.50, dto.getDeliveryPrice());
assertEquals("Seller1", dto.getMerchant());
}
}

View File

@@ -0,0 +1,103 @@
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;
import java.util.ArrayList;
import java.util.List;
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.util.ProductsConfig;
class CatalogueRetrieverTest {
private ProductsConfig productsConfig;
private ProductRetriever productRetriever;
private CatalogueRetriever catalogueRetriever;
@BeforeEach
public void setup() {
productsConfig = mock(ProductsConfig.class);
productRetriever = mock(ProductRetriever.class);
catalogueRetriever = new CatalogueRetriever(productsConfig, productRetriever);
}
@Test
void loadCatalogues_ValidConfig_CataloguesLoaded() throws ConfigurationException {
// Arrange
List<ProductCatalogue> productCatalogues = new ArrayList<>();
// Create a sample product catalogue with two products
ProductCatalogue productCatalogue = new ProductCatalogue("Catalogue 1", "Sample catalogue");
Product product1 = new Product();
product1.setDataOrigin("Amazon");
product1.setProductId("ASIN1");
productCatalogue.addProduct(product1);
Product product2 = new Product();
product2.setDataOrigin("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);
// Act
catalogueRetriever.loadCatalogues();
// Assert
List<ProductCatalogue> loadedCatalogues = catalogueRetriever.getProductCatalogues();
assertEquals(1, loadedCatalogues.size());
ProductCatalogue loadedCatalogue = loadedCatalogues.get(0);
assertEquals("Catalogue 1", loadedCatalogue.getProductName());
assertEquals("Sample catalogue", loadedCatalogue.getDescription());
List<Product> loadedProducts = loadedCatalogue.getProducts();
assertEquals(2, loadedProducts.size());
assertEquals(product1, loadedProducts.get(0));
assertEquals(product2, loadedProducts.get(1));
// 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());
}
}

View File

@@ -17,6 +17,7 @@ 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.model.Product;
import de.rwu.easydrop.util.Config;
@@ -33,6 +34,8 @@ class ProductRetrieverTest {
private ProductDTO productDTO;
@Mock
private Product product;
@Mock
private AbstractProductPersistence persistence;
private ProductRetriever productRetriever;
@@ -84,4 +87,25 @@ class ProductRetrieverTest {
assertEquals(9.99, result.getCurrentPrice());
verify(ebayDataSource, times(1)).getProductDTOById(productQuery);
}
@Test
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");
// Act
Product result = productRetriever.getProductFromPersistence(productId);
// Assert
assertEquals(productId, result.getProductId());
assertEquals(9.99, result.getCurrentPrice());
// Verify the interactions
verify(persistence, times(1)).getProductDTOById(productId);
}
}

View File

@@ -0,0 +1,69 @@
package de.rwu.easydrop.service.writer;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
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.dto.ProductDTO;
import de.rwu.easydrop.data.connector.AbstractProductPersistence;
import de.rwu.easydrop.model.Product;
import de.rwu.easydrop.model.ProductCatalogue;
class CatalogueWriterTest {
@Mock
private AbstractProductPersistence persistenceMock;
private CatalogueWriter catalogueWriter;
@BeforeEach
void setup() {
MockitoAnnotations.openMocks(this);
catalogueWriter = new CatalogueWriter(persistenceMock);
}
@Test
void writeCatalogues_ValidCatalogues_ProductsWrittenToPersistence() {
// Arrange
List<ProductCatalogue> catalogues = createSampleCatalogues();
// Act
catalogueWriter.writeCatalogues(catalogues);
// Assert
verify(persistenceMock, times(4)).saveProduct(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"));
ProductCatalogue catalogue2 = new ProductCatalogue("Catalogue 2", "Sample catalogue 2");
catalogue2.addProduct(createSampleProduct("Amazon", "ID 3"));
catalogue2.addProduct(createSampleProduct("eBay", "ID 4"));
catalogues.add(catalogue1);
catalogues.add(catalogue2);
return catalogues;
}
private Product createSampleProduct(String dataOrigin, String productId) {
Product product = new Product();
product.setDataOrigin(dataOrigin);
product.setProductId(productId);
product.setCurrentPrice(9999.99);
return product;
}
}

View File

@@ -0,0 +1,55 @@
package de.rwu.easydrop.service.writer;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
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.ProductDTO;
import de.rwu.easydrop.data.connector.AbstractProductPersistence;
import de.rwu.easydrop.model.Product;
class ProductWriterTest {
@Mock
private AbstractProductPersistence persistence;
private ProductWriter productWriter;
@BeforeEach
public void setup() {
MockitoAnnotations.openMocks(this);
productWriter = new ProductWriter();
productWriter.setPersistence(persistence);
}
@Test
void writeProductToPersistence_ValidProduct_CallsSaveProduct() {
// Arrange
Product product = new Product();
product.setProductId("12345");
product.setDataOrigin("Amazon");
product.setCurrentPrice(9.99);
// Act
productWriter.writeProductToPersistence(product);
// Assert
Mockito.verify(persistence).saveProduct(any(ProductDTO.class));
}
@Test
void writeProductToPersistence_InvalidProduct_ThrowsException() {
// Arrange
Product product = new Product();
product.setProductId("");
product.setDataOrigin("Amazon");
// Act and Assert
assertThrows(Exception.class, () -> productWriter.writeProductToPersistence(product));
}
}

View File

@@ -12,9 +12,9 @@ import javax.naming.ConfigurationException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
class ConfigImplTest {
class ConfigIntegrationTest {
private Config config;
private final static String TESTDATA_PATH = "src/test/resources/testdata.properties";
private final static String TESTDATA_PATH = "src/test/resources/test.config.properties";
private final static String TESTDATA_KEY = "API_KEY";
private final static String TESTDATA_VAL = "keyIsHere";
@@ -77,7 +77,7 @@ class ConfigImplTest {
@Test
void testLoadConfigSuccessfully() {
try {
config.setConfigLocation("src/test/resources/testdata.properties");
config.setConfigLocation("src/test/resources/test.config.properties");
config.loadConfig();
assertEquals(TESTDATA_VAL, config.getProperty(TESTDATA_KEY));
} catch (ConfigurationException e) {
@@ -98,7 +98,7 @@ class ConfigImplTest {
@Test
void testReset() throws ConfigurationException {
config.setConfigLocation("src/test/resources/testdata.properties");
config.setConfigLocation("src/test/resources/test.config.properties");
config.loadConfig();
assertNotNull(config.getProperty(TESTDATA_KEY));

View File

@@ -0,0 +1,89 @@
package de.rwu.easydrop.util;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.fail;
import java.util.List;
import javax.naming.ConfigurationException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import de.rwu.easydrop.model.ProductCatalogue;
class ProductsConfigIntegrationTest {
private ProductsConfig config;
private final static String TESTDATA_PATH = "src/test/resources/test.products-config.json";
private final static String TESTDATA_EMPTY_PATH = "src/test/resources/test.empty.products-config.json";
private final static String TESTDATA_MALFORMED_PATH = "src/test/resources/test.malformed.products-config.json";
@BeforeEach
void setUp() {
config = ProductsConfig.getInstance();
}
@Test
void testLoadConfigSuccessfully() {
try {
config.setConfigLocation(TESTDATA_PATH);
config.loadConfig();
String value = config.getProductCatalogues().get(0).getProductName();
assertEquals("Demo Product", value);
} catch (ConfigurationException e) {
fail("ConfigurationException should not be thrown");
}
}
@Test
void testLoadConfigMissingFile() {
config.setConfigLocation("path/that/doesnt/exist/products-config.json");
ConfigurationException exception = assertThrows(ConfigurationException.class, () -> {
config.loadConfig();
});
assertEquals("Couldn't load required products config file", exception.getMessage());
}
@Test
void testLoadConfigEmptyFile() {
config.setConfigLocation(TESTDATA_EMPTY_PATH);
ConfigurationException exception = assertThrows(ConfigurationException.class, () -> {
config.loadConfig();
});
assertEquals("Products config is empty or malformed", exception.getMessage());
}
@Test
void testLoadConfigMalformedFile() {
config.setConfigLocation(TESTDATA_MALFORMED_PATH);
ConfigurationException exception = assertThrows(ConfigurationException.class, () -> {
config.loadConfig();
});
assertEquals("Products config is empty or malformed", exception.getMessage());
}
@Test
void testReset() {
try {
config.setConfigLocation(TESTDATA_PATH);
config.loadConfig();
} catch (ConfigurationException e) {
fail("ConfigurationException should not be thrown");
}
assertNotNull(config.getProductCatalogues());
config.reset();
List<ProductCatalogue> pCats = config.getProductCatalogues();
assertEquals(0, pCats.size(), "Catalogues list should be empty");
}
}

View File

@@ -0,0 +1,44 @@
package de.rwu.easydrop.util;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.mockito.Mockito.spy;
import javax.naming.ConfigurationException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockitoAnnotations;
class ProductsConfigTest {
private ProductsConfig productsConfig;
@BeforeEach
void setUp() throws ConfigurationException {
MockitoAnnotations.openMocks(this);
productsConfig = spy(ProductsConfig.getInstance());
}
@Test
void testGetInstance() {
ProductsConfig newConfig = ProductsConfig.getInstance();
assertNotNull(newConfig);
}
@Test
void testGetInstanceEquality() {
// Create "two" instances to check validity of Singleton pattern
ProductsConfig instance1 = ProductsConfig.getInstance();
ProductsConfig instance2 = ProductsConfig.getInstance();
assertSame(instance1, instance2, "Instances should be equal");
}
@Test
void testSetConfigLocation() {
String newPath = "new/location/config.properties";
productsConfig.setConfigLocation(newPath);
assertEquals(newPath, productsConfig.getConfigLocation());
}
}

View File

@@ -0,0 +1,15 @@
{
"products": [
{
"name": "Demo Product",
description: "Integration Testing Product",
"identifiers": [
{
"Amazon": "DEMO-AMAZON-001"
},
{
"eBay": "DEMO-EBAY-001"
}
]
]
}

View File

@@ -0,0 +1,16 @@
{
"products": [
{
"name": "Demo Product",
"description": "Integration Testing Product",
"identifiers": [
{
"Amazon": "DEMO-AMAZON-001"
},
{
"eBay": "DEMO-EBAY-001"
}
]
}
]
}