#53 Implemented SQLite product data persistence + tests

This commit is contained in:
Marvin Scham
2023-06-07 23:17:59 +02:00
parent 0a42a38016
commit 5a6ff71839
27 changed files with 880 additions and 34 deletions

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

@@ -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

@@ -1,6 +1,7 @@
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;
@@ -13,6 +14,7 @@ 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;
@@ -40,11 +42,11 @@ class CatalogueRetrieverTest {
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
@@ -72,4 +74,30 @@ class CatalogueRetrieverTest {
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

@@ -1,14 +1,19 @@
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";
@@ -65,4 +70,20 @@ class ProductsConfigIntegrationTest {
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");
}
}