diff --git a/pom.xml b/pom.xml index 63566994ee..57a26fff51 100644 --- a/pom.xml +++ b/pom.xml @@ -33,6 +33,12 @@ ${junit.jupiter.version} test + + org.mockito + mockito-core + 3.9.0 + test + diff --git a/src/main/java/core/basesyntax/HelloWorld.java b/src/main/java/core/basesyntax/HelloWorld.java deleted file mode 100644 index e758b17650..0000000000 --- a/src/main/java/core/basesyntax/HelloWorld.java +++ /dev/null @@ -1,7 +0,0 @@ -package core.basesyntax; - -/** - * Feel free to remove this class and create your own. - */ -public class HelloWorld { -} diff --git a/src/main/java/core/basesyntax/Main.java b/src/main/java/core/basesyntax/Main.java new file mode 100644 index 0000000000..a9dd9c4ac9 --- /dev/null +++ b/src/main/java/core/basesyntax/Main.java @@ -0,0 +1,62 @@ +package core.basesyntax; + +import core.basesyntax.db.Storage; +import core.basesyntax.impl.BalanceHandler; +import core.basesyntax.impl.CsvReportCreator; +import core.basesyntax.impl.CsvTransactionParser; +import core.basesyntax.impl.DefaultOperationStrategy; +import core.basesyntax.impl.FileReaderServiceImpl; +import core.basesyntax.model.FruitTransaction; +import core.basesyntax.report.ReportCreator; +import core.basesyntax.report.WriterService; +import core.basesyntax.report.WriterServiceImpl; +import core.basesyntax.service.FileReaderService; +import core.basesyntax.service.PurchaseHandler; +import core.basesyntax.service.ReturnHandler; +import core.basesyntax.service.SupplyHandler; +import core.basesyntax.service.TransactionProcessor; +import core.basesyntax.strategy.OperationHandler; +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class Main { + public static void main(String[] args) throws IOException { + String inputFilePath = "input.csv"; + final String outputFilePath = "output.csv"; + + FileReaderService fileReaderService = new FileReaderServiceImpl(); + List transactionData; + try { + transactionData = fileReaderService.readData(inputFilePath); + } catch (IOException e) { + System.err.println("Error opening/reading file: " + e.getMessage()); + return; + } + + Map customHandlers = new HashMap<>(); + customHandlers.put(FruitTransaction.Operation.BALANCE, new BalanceHandler()); + customHandlers.put(FruitTransaction.Operation.SUPPLY, new SupplyHandler()); + customHandlers.put(FruitTransaction.Operation.PURCHASE, new PurchaseHandler()); + customHandlers.put(FruitTransaction.Operation.RETURN, new ReturnHandler()); + + DefaultOperationStrategy operationStrategy = new DefaultOperationStrategy(customHandlers); + + List transactions; + transactions = new CsvTransactionParser().parseTransactions(transactionData); + + Storage storage = new Storage(); + + TransactionProcessor transactionProcessor; + transactionProcessor = new TransactionProcessor(operationStrategy, storage); + transactionProcessor.processTransactions(transactions); + + WriterService writerService = new WriterServiceImpl(); + + ReportCreator reportCreator = new CsvReportCreator(writerService, outputFilePath); + + Map fruitInventory = storage.getFruitInventory(); + reportCreator.createReport(fruitInventory, outputFilePath); + } +} diff --git a/src/main/java/core/basesyntax/db/Storage.java b/src/main/java/core/basesyntax/db/Storage.java new file mode 100644 index 0000000000..3d88ffb3dc --- /dev/null +++ b/src/main/java/core/basesyntax/db/Storage.java @@ -0,0 +1,12 @@ +package core.basesyntax.db; + +import java.util.HashMap; +import java.util.Map; + +public class Storage { + private Map fruitInventory = new HashMap<>(); + + public Map getFruitInventory() { + return fruitInventory; + } +} diff --git a/src/main/java/core/basesyntax/impl/BalanceHandler.java b/src/main/java/core/basesyntax/impl/BalanceHandler.java new file mode 100644 index 0000000000..a0ea6c0822 --- /dev/null +++ b/src/main/java/core/basesyntax/impl/BalanceHandler.java @@ -0,0 +1,15 @@ +package core.basesyntax.impl; + +import core.basesyntax.model.FruitTransaction; +import core.basesyntax.strategy.OperationHandler; +import java.util.Map; + +public class BalanceHandler implements OperationHandler { + @Override + public void handleTransaction(FruitTransaction transaction, Map storage) { + String fruit = transaction.getFruit(); + int quantity = transaction.getQuantity(); + + storage.put(fruit, quantity); + } +} diff --git a/src/main/java/core/basesyntax/impl/CsvReportCreator.java b/src/main/java/core/basesyntax/impl/CsvReportCreator.java new file mode 100644 index 0000000000..6e421871c0 --- /dev/null +++ b/src/main/java/core/basesyntax/impl/CsvReportCreator.java @@ -0,0 +1,37 @@ +package core.basesyntax.impl; + +import core.basesyntax.report.ReportCreator; +import core.basesyntax.report.ReportService; +import core.basesyntax.report.WriterService; +import java.io.IOException; +import java.util.Map; + +public class CsvReportCreator implements ReportService, ReportCreator { + private final WriterService writerService; + private final String outputPath; + + public CsvReportCreator(WriterService writerService, String outputPath) { + this.writerService = writerService; + this.outputPath = outputPath; + } + + @Override + public String generateReport(Map fruitInventory) { + StringBuilder report = new StringBuilder("Fruit,Quantity\n"); + for (Map.Entry entry : fruitInventory.entrySet()) { + report.append(entry.getKey()).append(",").append(entry.getValue()).append("\n"); + } + return report.toString(); + } + + @Override + public void createReport(Map fruitInventory) throws IOException { + String report = generateReport(fruitInventory); + writerService.writeToFile(report, outputPath); + } + + @Override + public void createReport(Map fruitInventory, + String filePath) throws IOException { + } +} diff --git a/src/main/java/core/basesyntax/impl/CsvTransactionParser.java b/src/main/java/core/basesyntax/impl/CsvTransactionParser.java new file mode 100644 index 0000000000..83c12bcbb2 --- /dev/null +++ b/src/main/java/core/basesyntax/impl/CsvTransactionParser.java @@ -0,0 +1,31 @@ +package core.basesyntax.impl; + +import core.basesyntax.model.FruitTransaction; +import core.basesyntax.service.TransactionParser; +import java.util.ArrayList; +import java.util.List; + +public class CsvTransactionParser implements TransactionParser { + private static final String SEPARATOR = ","; + private static final int OPERATION_CODE_INDEX = 0; + private static final int FRUIT_INDEX = 1; + + @Override + public List parseTransactions(List data) { + List transactions = new ArrayList<>(); + for (String line : data) { + String[] parts = line.split(SEPARATOR); + if (parts.length == 3) { + String operationCode = parts[OPERATION_CODE_INDEX]; + String fruit = parts[FRUIT_INDEX]; + int quantity = Integer.parseInt(parts[2]); + transactions.add(new FruitTransaction( + FruitTransaction.Operation.valueOf(operationCode), + fruit, + quantity + )); + } + } + return transactions; + } +} diff --git a/src/main/java/core/basesyntax/impl/DefaultOperationStrategy.java b/src/main/java/core/basesyntax/impl/DefaultOperationStrategy.java new file mode 100644 index 0000000000..ef311401d4 --- /dev/null +++ b/src/main/java/core/basesyntax/impl/DefaultOperationStrategy.java @@ -0,0 +1,19 @@ +package core.basesyntax.impl; + +import core.basesyntax.model.FruitTransaction; +import core.basesyntax.strategy.OperationHandler; +import core.basesyntax.strategy.OperationStrategy; +import java.util.Map; + +public class DefaultOperationStrategy implements OperationStrategy { + private Map handlers; + + public DefaultOperationStrategy(Map handlers) { + this.handlers = handlers; + } + + @Override + public OperationHandler getHandler(FruitTransaction.Operation operation) { + return handlers.get(operation); + } +} diff --git a/src/main/java/core/basesyntax/impl/FileReaderServiceImpl.java b/src/main/java/core/basesyntax/impl/FileReaderServiceImpl.java new file mode 100644 index 0000000000..5a5e59c740 --- /dev/null +++ b/src/main/java/core/basesyntax/impl/FileReaderServiceImpl.java @@ -0,0 +1,24 @@ +package core.basesyntax.impl; + +import core.basesyntax.service.FileReaderService; +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class FileReaderServiceImpl implements FileReaderService { + @Override + public List readData(String filePath) { + List data = new ArrayList<>(); + try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) { + String line; + while ((line = reader.readLine()) != null) { + data.add(line); + } + } catch (IOException e) { + throw new RuntimeException("Error reading data from file: " + e.getMessage(), e); + } + return data; + } +} diff --git a/src/main/java/core/basesyntax/impl/TextFileWriter.java b/src/main/java/core/basesyntax/impl/TextFileWriter.java new file mode 100644 index 0000000000..e465d5757c --- /dev/null +++ b/src/main/java/core/basesyntax/impl/TextFileWriter.java @@ -0,0 +1,15 @@ +package core.basesyntax.impl; + +import core.basesyntax.service.TextFileWriterInterface; +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.io.IOException; + +public class TextFileWriter implements TextFileWriterInterface { + @Override + public void writeText(String text, String filePath) throws IOException { + try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath))) { + writer.write(text); + } + } +} diff --git a/src/main/java/core/basesyntax/model/FruitTransaction.java b/src/main/java/core/basesyntax/model/FruitTransaction.java new file mode 100644 index 0000000000..082c1d204b --- /dev/null +++ b/src/main/java/core/basesyntax/model/FruitTransaction.java @@ -0,0 +1,63 @@ +package core.basesyntax.model; + +public class FruitTransaction { + private Operation operation; + private String fruit; + private int quantity; + + public FruitTransaction(Operation operation, String fruit, int quantity) { + this.operation = operation; + this.fruit = fruit; + this.quantity = quantity; + } + + public Operation getOperation() { + return operation; + } + + public void setOperation(Operation operation) { + this.operation = operation; + } + + public String getFruit() { + return fruit; + } + + public void setFruit(String fruit) { + this.fruit = fruit; + } + + public int getQuantity() { + return quantity; + } + + public void setQuantity(int quantity) { + this.quantity = quantity; + } + + public enum Operation { + BALANCE("b"), + SUPPLY("s"), + PURCHASE("p"), + RETURN("r"); + + private String code; + + Operation(String code) { + this.code = code; + } + + public String getCode() { + return code; + } + } + + public static Operation getByCode(String character) { + for (Operation operation : Operation.values()) { + if (operation.getCode().equals(character)) { + return operation; + } + } + throw new RuntimeException("Unknown operation"); + } +} diff --git a/src/main/java/core/basesyntax/report/ReportCreator.java b/src/main/java/core/basesyntax/report/ReportCreator.java new file mode 100644 index 0000000000..31c5b4758e --- /dev/null +++ b/src/main/java/core/basesyntax/report/ReportCreator.java @@ -0,0 +1,8 @@ +package core.basesyntax.report; + +import java.io.IOException; +import java.util.Map; + +public interface ReportCreator { + void createReport(Map fruitInventory, String filePath) throws IOException; +} diff --git a/src/main/java/core/basesyntax/report/ReportService.java b/src/main/java/core/basesyntax/report/ReportService.java new file mode 100644 index 0000000000..a0ed65cf6f --- /dev/null +++ b/src/main/java/core/basesyntax/report/ReportService.java @@ -0,0 +1,10 @@ +package core.basesyntax.report; + +import java.io.IOException; +import java.util.Map; + +public interface ReportService { + String generateReport(Map fruitInventory); + + void createReport(Map fruitInventory) throws IOException; +} diff --git a/src/main/java/core/basesyntax/report/WriterService.java b/src/main/java/core/basesyntax/report/WriterService.java new file mode 100644 index 0000000000..799d4e09cc --- /dev/null +++ b/src/main/java/core/basesyntax/report/WriterService.java @@ -0,0 +1,7 @@ +package core.basesyntax.report; + +import java.io.IOException; + +public interface WriterService { + void writeToFile(String data, String outputPath) throws IOException; +} diff --git a/src/main/java/core/basesyntax/report/WriterServiceImpl.java b/src/main/java/core/basesyntax/report/WriterServiceImpl.java new file mode 100644 index 0000000000..06390e1f73 --- /dev/null +++ b/src/main/java/core/basesyntax/report/WriterServiceImpl.java @@ -0,0 +1,13 @@ +package core.basesyntax.report; + +import java.io.FileWriter; +import java.io.IOException; + +public class WriterServiceImpl implements WriterService { + @Override + public void writeToFile(String data, String outputPath) throws IOException { + try (FileWriter writer = new FileWriter(outputPath)) { + writer.write(data); + } + } +} diff --git a/src/main/java/core/basesyntax/service/FileReaderService.java b/src/main/java/core/basesyntax/service/FileReaderService.java new file mode 100644 index 0000000000..d3135d76b5 --- /dev/null +++ b/src/main/java/core/basesyntax/service/FileReaderService.java @@ -0,0 +1,8 @@ +package core.basesyntax.service; + +import java.io.IOException; +import java.util.List; + +public interface FileReaderService { + List readData(String filePath) throws IOException; +} diff --git a/src/main/java/core/basesyntax/service/PurchaseHandler.java b/src/main/java/core/basesyntax/service/PurchaseHandler.java new file mode 100644 index 0000000000..4accfec5cf --- /dev/null +++ b/src/main/java/core/basesyntax/service/PurchaseHandler.java @@ -0,0 +1,16 @@ +package core.basesyntax.service; + +import core.basesyntax.model.FruitTransaction; +import core.basesyntax.strategy.OperationHandler; +import java.util.Map; + +public class PurchaseHandler implements OperationHandler { + @Override + public void handleTransaction(FruitTransaction transaction, Map storage) { + String fruit = transaction.getFruit(); + int quantity = transaction.getQuantity(); + + int currentQuantity = storage.getOrDefault(fruit, 0); + storage.put(fruit, currentQuantity - quantity); + } +} diff --git a/src/main/java/core/basesyntax/service/ReturnHandler.java b/src/main/java/core/basesyntax/service/ReturnHandler.java new file mode 100644 index 0000000000..35bca71b08 --- /dev/null +++ b/src/main/java/core/basesyntax/service/ReturnHandler.java @@ -0,0 +1,16 @@ +package core.basesyntax.service; + +import core.basesyntax.model.FruitTransaction; +import core.basesyntax.strategy.OperationHandler; +import java.util.Map; + +public class ReturnHandler implements OperationHandler { + @Override + public void handleTransaction(FruitTransaction transaction, Map storage) { + String fruit = transaction.getFruit(); + int quantity = transaction.getQuantity(); + + int currentQuantity = storage.getOrDefault(fruit, 0); + storage.put(fruit, currentQuantity + quantity); + } +} diff --git a/src/main/java/core/basesyntax/service/SupplyHandler.java b/src/main/java/core/basesyntax/service/SupplyHandler.java new file mode 100644 index 0000000000..e69ace3b0e --- /dev/null +++ b/src/main/java/core/basesyntax/service/SupplyHandler.java @@ -0,0 +1,16 @@ +package core.basesyntax.service; + +import core.basesyntax.model.FruitTransaction; +import core.basesyntax.strategy.OperationHandler; +import java.util.Map; + +public class SupplyHandler implements OperationHandler { + @Override + public void handleTransaction(FruitTransaction transaction, Map storage) { + String fruit = transaction.getFruit(); + int quantity = transaction.getQuantity(); + + int currentQuantity = storage.getOrDefault(fruit, 0); + storage.put(fruit, currentQuantity + quantity); + } +} diff --git a/src/main/java/core/basesyntax/service/TextFileWriterInterface.java b/src/main/java/core/basesyntax/service/TextFileWriterInterface.java new file mode 100644 index 0000000000..aec72b9145 --- /dev/null +++ b/src/main/java/core/basesyntax/service/TextFileWriterInterface.java @@ -0,0 +1,7 @@ +package core.basesyntax.service; + +import java.io.IOException; + +public interface TextFileWriterInterface { + void writeText(String text, String filePath) throws IOException; +} diff --git a/src/main/java/core/basesyntax/service/TransactionParser.java b/src/main/java/core/basesyntax/service/TransactionParser.java new file mode 100644 index 0000000000..5621e63ab6 --- /dev/null +++ b/src/main/java/core/basesyntax/service/TransactionParser.java @@ -0,0 +1,8 @@ +package core.basesyntax.service; + +import core.basesyntax.model.FruitTransaction; +import java.util.List; + +public interface TransactionParser { + List parseTransactions(List data); +} diff --git a/src/main/java/core/basesyntax/service/TransactionProcessor.java b/src/main/java/core/basesyntax/service/TransactionProcessor.java new file mode 100644 index 0000000000..696e1ca3ae --- /dev/null +++ b/src/main/java/core/basesyntax/service/TransactionProcessor.java @@ -0,0 +1,24 @@ +package core.basesyntax.service; + +import core.basesyntax.db.Storage; +import core.basesyntax.model.FruitTransaction; +import core.basesyntax.strategy.OperationHandler; +import core.basesyntax.strategy.OperationStrategy; +import java.util.List; + +public class TransactionProcessor { + private OperationStrategy operationStrategy; + private Storage storage; + + public TransactionProcessor(OperationStrategy operationStrategy, Storage storage) { + this.operationStrategy = operationStrategy; + this.storage = storage; + } + + public void processTransactions(List transactions) { + for (FruitTransaction transaction : transactions) { + OperationHandler handler = operationStrategy.getHandler(transaction.getOperation()); + handler.handleTransaction(transaction, storage.getFruitInventory()); + } + } +} diff --git a/src/main/java/core/basesyntax/strategy/OperationHandler.java b/src/main/java/core/basesyntax/strategy/OperationHandler.java new file mode 100644 index 0000000000..4b5f4b191b --- /dev/null +++ b/src/main/java/core/basesyntax/strategy/OperationHandler.java @@ -0,0 +1,8 @@ +package core.basesyntax.strategy; + +import core.basesyntax.model.FruitTransaction; +import java.util.Map; + +public interface OperationHandler { + void handleTransaction(FruitTransaction transaction, Map storage); +} diff --git a/src/main/java/core/basesyntax/strategy/OperationStrategy.java b/src/main/java/core/basesyntax/strategy/OperationStrategy.java new file mode 100644 index 0000000000..e9f644c32b --- /dev/null +++ b/src/main/java/core/basesyntax/strategy/OperationStrategy.java @@ -0,0 +1,7 @@ +package core.basesyntax.strategy; + +import core.basesyntax.model.FruitTransaction; + +public interface OperationStrategy { + OperationHandler getHandler(FruitTransaction.Operation operation); +} diff --git a/src/test/java/core/basesyntax/db/StorageTest.java b/src/test/java/core/basesyntax/db/StorageTest.java new file mode 100644 index 0000000000..4c93d0b07e --- /dev/null +++ b/src/test/java/core/basesyntax/db/StorageTest.java @@ -0,0 +1,42 @@ +package core.basesyntax.db; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class StorageTest { + private Storage storage; + + @BeforeEach + public void setUp() { + storage = new Storage(); + } + + @Test + public void testFruitInventoryIsEmptyInitially() { + assertTrue(storage.getFruitInventory().isEmpty()); + } + + @Test + public void testAddToFruitInventory() { + storage.getFruitInventory().put("apple", 10); + storage.getFruitInventory().put("banana", 5); + + assertEquals(10, storage.getFruitInventory().get("apple")); + assertEquals(5, storage.getFruitInventory().get("banana")); + } + + @Test + public void testRemoveFromFruitInventory() { + storage.getFruitInventory().put("apple", 10); + storage.getFruitInventory().put("banana", 5); + + storage.getFruitInventory().remove("apple"); + + assertNull(storage.getFruitInventory().get("apple")); + assertEquals(5, storage.getFruitInventory().get("banana")); + } +} diff --git a/src/test/java/core/basesyntax/impl/BalanceHandlerTest.java b/src/test/java/core/basesyntax/impl/BalanceHandlerTest.java new file mode 100644 index 0000000000..d0931c5018 --- /dev/null +++ b/src/test/java/core/basesyntax/impl/BalanceHandlerTest.java @@ -0,0 +1,45 @@ +package core.basesyntax.impl; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import core.basesyntax.model.FruitTransaction; +import core.basesyntax.strategy.OperationHandler; +import java.util.HashMap; +import java.util.Map; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class BalanceHandlerTest { + private OperationHandler balanceHandler; + private Map storage; + + @BeforeEach + public void setUp() { + balanceHandler = new BalanceHandler(); + storage = new HashMap<>(); + } + + @Test + public void testHandleTransaction_AddsToFruitInventory() { + FruitTransaction transaction = new FruitTransaction( + FruitTransaction.Operation.BALANCE, "apple", 10); + + balanceHandler.handleTransaction(transaction, storage); + + assertEquals(10, storage.get("apple")); + } + + @Test + public void testHandleTransaction_AddsMultipleToFruitInventory() { + FruitTransaction transaction1 = new FruitTransaction( + FruitTransaction.Operation.BALANCE, "apple", 5); + FruitTransaction transaction2 = new FruitTransaction( + FruitTransaction.Operation.BALANCE, "banana", 7); + + balanceHandler.handleTransaction(transaction1, storage); + balanceHandler.handleTransaction(transaction2, storage); + + assertEquals(5, storage.get("apple")); + assertEquals(7, storage.get("banana")); + } +} diff --git a/src/test/java/core/basesyntax/impl/CsvReportCreatorGenerateReportTest.java b/src/test/java/core/basesyntax/impl/CsvReportCreatorGenerateReportTest.java new file mode 100644 index 0000000000..a6d5c4358d --- /dev/null +++ b/src/test/java/core/basesyntax/impl/CsvReportCreatorGenerateReportTest.java @@ -0,0 +1,44 @@ +package core.basesyntax.impl; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; + +import core.basesyntax.report.WriterService; +import java.util.HashMap; +import java.util.Map; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class CsvReportCreatorGenerateReportTest { + private CsvReportCreator csvReportCreator; + + @BeforeEach + public void setUp() { + WriterService writerService = mock(WriterService.class); + csvReportCreator = new CsvReportCreator(writerService, "output.csv"); + } + + @Test + public void testGenerateReportWithFruitInventory() { + Map fruitInventory = new HashMap<>(); + fruitInventory.put("Apple", 5); + fruitInventory.put("Banana", 10); + + String expectedReport = "Fruit,Quantity\nApple,5\nBanana,10\n"; + + String actualReport = csvReportCreator.generateReport(fruitInventory); + + assertEquals(expectedReport, actualReport); + } + + @Test + public void testGenerateReportWithEmptyFruitInventory() { + Map fruitInventory = new HashMap<>(); + + String expectedReport = "Fruit,Quantity\n"; + + String actualReport = csvReportCreator.generateReport(fruitInventory); + + assertEquals(expectedReport, actualReport); + } +} diff --git a/src/test/java/core/basesyntax/impl/CsvTransactionParserTest.java b/src/test/java/core/basesyntax/impl/CsvTransactionParserTest.java new file mode 100644 index 0000000000..4e1887df04 --- /dev/null +++ b/src/test/java/core/basesyntax/impl/CsvTransactionParserTest.java @@ -0,0 +1,66 @@ +package core.basesyntax.impl; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import core.basesyntax.model.FruitTransaction; +import core.basesyntax.service.TransactionParser; +import java.util.ArrayList; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class CsvTransactionParserTest { + private TransactionParser transactionParser; + + @BeforeEach + void setUp() { + transactionParser = new CsvTransactionParser(); + } + + @Test + void parseTransactions_WhenGivenValidData_ReturnsListOfTransactions() { + List data = new ArrayList<>(); + data.add("SUPPLY,apple,10"); + data.add("PURCHASE,banana,5"); + + List expectedTransactions = new ArrayList<>(); + expectedTransactions.add( + new FruitTransaction(FruitTransaction.Operation.SUPPLY, "apple", 10) + ); + expectedTransactions.add( + new FruitTransaction(FruitTransaction.Operation.PURCHASE, "banana", 5) + ); + + List parsedTransactions = transactionParser.parseTransactions(data); + + assertEquals(expectedTransactions.size(), parsedTransactions.size()); + + for (int i = 0; i < expectedTransactions.size(); i++) { + FruitTransaction expected = expectedTransactions.get(i); + FruitTransaction actual = parsedTransactions.get(i); + + assertEquals(expected.getOperation(), actual.getOperation()); + assertEquals(expected.getFruit(), actual.getFruit()); + assertEquals(expected.getQuantity(), actual.getQuantity()); + } + } + + @Test + void parseTransactions_WhenGivenInvalidData_ReturnsEmptyList() { + List data = new ArrayList<>(); + data.add("ADD,apple"); + + List parsedTransactions = transactionParser.parseTransactions(data); + + assertEquals(0, parsedTransactions.size()); + } + + @Test + void parseTransactions_WhenGivenEmptyData_ReturnsEmptyList() { + List data = new ArrayList<>(); + + List parsedTransactions = transactionParser.parseTransactions(data); + + assertEquals(0, parsedTransactions.size()); + } +} diff --git a/src/test/java/core/basesyntax/impl/DefaultOperationStrategyTest.java b/src/test/java/core/basesyntax/impl/DefaultOperationStrategyTest.java new file mode 100644 index 0000000000..fd6def4049 --- /dev/null +++ b/src/test/java/core/basesyntax/impl/DefaultOperationStrategyTest.java @@ -0,0 +1,48 @@ +package core.basesyntax.impl; + +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import core.basesyntax.model.FruitTransaction; +import core.basesyntax.service.PurchaseHandler; +import core.basesyntax.service.SupplyHandler; +import core.basesyntax.strategy.OperationHandler; +import core.basesyntax.strategy.OperationStrategy; +import java.util.HashMap; +import java.util.Map; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +class DefaultOperationStrategyTest { + private OperationStrategy operationStrategy; + + @BeforeEach + void setUp() { + Map handlers = new HashMap<>(); + handlers.put(FruitTransaction.Operation.SUPPLY, Mockito.mock(SupplyHandler.class)); + handlers.put(FruitTransaction.Operation.PURCHASE, Mockito.mock(PurchaseHandler.class)); + operationStrategy = new DefaultOperationStrategy(handlers); + } + + @Test + void getHandler_WhenValidOperationSupplied_ReturnsSupplyHandler() { + OperationHandler actualHandler; + actualHandler = operationStrategy.getHandler(FruitTransaction.Operation.SUPPLY); + assertTrue(actualHandler instanceof SupplyHandler); + } + + @Test + void getHandler_WhenInvalidOperationSupplied_ReturnsNull() { + assertNull(operationStrategy.getHandler(FruitTransaction.Operation.BALANCE)); + } + + @Test + void getHandler_WhenEmptyHandlersMap_ReturnsNull() { + Map emptyHandlers = new HashMap<>(); + operationStrategy = new DefaultOperationStrategy(emptyHandlers); + + assertNull(operationStrategy.getHandler(FruitTransaction.Operation.SUPPLY)); + assertNull(operationStrategy.getHandler(FruitTransaction.Operation.PURCHASE)); + } +} diff --git a/src/test/java/core/basesyntax/impl/FileReaderServiceImplTest.java b/src/test/java/core/basesyntax/impl/FileReaderServiceImplTest.java new file mode 100644 index 0000000000..4aa5ac97dd --- /dev/null +++ b/src/test/java/core/basesyntax/impl/FileReaderServiceImplTest.java @@ -0,0 +1,56 @@ +package core.basesyntax.impl; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import core.basesyntax.service.FileReaderService; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.List; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class FileReaderServiceImplTest { + private FileReaderService fileReaderService; + private File tempFile; + + @BeforeEach + void setUp() throws IOException { + fileReaderService = new FileReaderServiceImpl(); + tempFile = File.createTempFile("testFile", ".txt"); + try (FileWriter writer = new FileWriter(tempFile)) { + writer.write("Line 1\nLine 2\nLine 3"); + } + } + + @AfterEach + void tearDown() { + if (tempFile != null && tempFile.exists()) { + tempFile.delete(); + } + } + + @Test + void testReadDataFromFile() throws IOException { + List data = fileReaderService.readData(tempFile.getPath()); + assertEquals(3, data.size()); + assertEquals("Line 1", data.get(0)); + assertEquals("Line 2", data.get(1)); + assertEquals("Line 3", data.get(2)); + } + + @Test + void testReadDataFromNonExistentFile() { + assertThrows(RuntimeException.class, + () -> fileReaderService.readData("nonexistentfile.txt")); + } + + @Test + void testReadDataFromEmptyFile() throws IOException { + File emptyFile = File.createTempFile("emptyFile", ".txt"); + List data = fileReaderService.readData(emptyFile.getPath()); + assertEquals(0, data.size()); + } +} diff --git a/src/test/java/core/basesyntax/impl/TextFileWriterTest.java b/src/test/java/core/basesyntax/impl/TextFileWriterTest.java new file mode 100644 index 0000000000..f5097c4b23 --- /dev/null +++ b/src/test/java/core/basesyntax/impl/TextFileWriterTest.java @@ -0,0 +1,39 @@ +package core.basesyntax.impl; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import core.basesyntax.service.TextFileWriterInterface; +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class TextFileWriterTest { + private TextFileWriterInterface textFileWriter; + private String tempFilePath; + + @BeforeEach + void setUp() { + textFileWriter = new TextFileWriter(); + tempFilePath = "tempFile.txt"; + } + + @Test + void writeText_ValidTextAndFilePath_TextWrittenToFile() throws IOException { + String text = "This is a test text."; + textFileWriter.writeText(text, tempFilePath); + + try (BufferedReader reader = new BufferedReader(new FileReader(tempFilePath))) { + String line = reader.readLine(); + assertEquals(text, line); + } + } + + @Test + void writeText_InvalidFilePath_IoExceptionThrown() { + assertThrows(IOException.class, () -> textFileWriter.writeText("Text", + "nonexistentfolder/nonexistentfile.txt")); + } +} diff --git a/src/test/java/core/basesyntax/model/FruitTransactionTest.java b/src/test/java/core/basesyntax/model/FruitTransactionTest.java new file mode 100644 index 0000000000..da9ba78c6a --- /dev/null +++ b/src/test/java/core/basesyntax/model/FruitTransactionTest.java @@ -0,0 +1,64 @@ +package core.basesyntax.model; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class FruitTransactionTest { + private FruitTransaction fruitTransaction; + + @BeforeEach + void setUp() { + fruitTransaction = new FruitTransaction(FruitTransaction.Operation.SUPPLY, "apple", 10); + } + + @Test + void getOperation_ValidTransaction_ReturnsOperation() { + assertEquals(FruitTransaction.Operation.SUPPLY, fruitTransaction.getOperation()); + } + + @Test + void setOperation_ValidOperation_OperationIsSet() { + fruitTransaction.setOperation(FruitTransaction.Operation.PURCHASE); + assertEquals(FruitTransaction.Operation.PURCHASE, fruitTransaction.getOperation()); + } + + @Test + void getFruit_ValidTransaction_ReturnsFruit() { + assertEquals("apple", fruitTransaction.getFruit()); + } + + @Test + void setFruit_ValidFruit_FruitIsSet() { + fruitTransaction.setFruit("banana"); + assertEquals("banana", fruitTransaction.getFruit()); + } + + @Test + void getQuantity_ValidTransaction_ReturnsQuantity() { + assertEquals(10, fruitTransaction.getQuantity()); + } + + @Test + void setQuantity_ValidQuantity_QuantityIsSet() { + fruitTransaction.setQuantity(5); + assertEquals(5, fruitTransaction.getQuantity()); + } + + @Test + void enumValues_EnumValuesExist_EnumValuesCountMatches() { + assertEquals(4, FruitTransaction.Operation.values().length); + } + + @Test + void getByCode_ExistingCode_ReturnsOperation() { + assertEquals(FruitTransaction.Operation.SUPPLY, FruitTransaction.getByCode("s")); + } + + @Test + void getByCode_UnknownCode_RuntimeExceptionThrown() { + assertThrows(RuntimeException.class, () -> FruitTransaction.getByCode("x")); + } +} diff --git a/src/test/java/core/basesyntax/report/WriterServiceImplTest.java b/src/test/java/core/basesyntax/report/WriterServiceImplTest.java new file mode 100644 index 0000000000..8d253d4551 --- /dev/null +++ b/src/test/java/core/basesyntax/report/WriterServiceImplTest.java @@ -0,0 +1,38 @@ +package core.basesyntax.report; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class WriterServiceImplTest { + private WriterService writerService; + private String outputPath; + + @BeforeEach + void setUp() { + writerService = new WriterServiceImpl(); + outputPath = "test-output.txt"; + } + + @Test + void writeToFile_ValidData_FileContainsData() throws IOException { + String data = "This is a test data"; + writerService.writeToFile(data, outputPath); + + Path path = Paths.get(outputPath); + String content = new String(Files.readAllBytes(path)); + assertEquals(data, content); + } + + @Test + void writeToFile_InvalidPath_IOexceptionThrown() { + assertThrows(IOException.class, () -> writerService.writeToFile("Data", + "/nonexistentfolder/nonexistentfile.txt")); + } +} diff --git a/src/test/java/core/basesyntax/service/PurchaseHandlerTest.java b/src/test/java/core/basesyntax/service/PurchaseHandlerTest.java new file mode 100644 index 0000000000..a2b7b25df7 --- /dev/null +++ b/src/test/java/core/basesyntax/service/PurchaseHandlerTest.java @@ -0,0 +1,51 @@ +package core.basesyntax.service; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import core.basesyntax.model.FruitTransaction; +import java.util.HashMap; +import java.util.Map; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class PurchaseHandlerTest { + private PurchaseHandler purchaseHandler; + + @BeforeEach + void setUp() { + purchaseHandler = new PurchaseHandler(); + } + + @Test + void testHandleTransaction() { + Map storage = new HashMap<>(); + storage.put("apple", 10); + storage.put("banana", 5); + + FruitTransaction transaction = new FruitTransaction(FruitTransaction.Operation.PURCHASE, + "apple", + 3); + + purchaseHandler.handleTransaction(transaction, storage); + + assertEquals(7, storage.get("apple")); + + assertEquals(5, storage.get("banana")); + } + + @Test + void testHandleTransactionWhenFruitNotInStorage() { + Map storage = new HashMap<>(); + storage.put("banana", 5); + + FruitTransaction transaction = new FruitTransaction(FruitTransaction.Operation.PURCHASE, + "apple", + 3); + + purchaseHandler.handleTransaction(transaction, storage); + + assertEquals(-3, storage.get("apple")); + + assertEquals(5, storage.get("banana")); + } +} diff --git a/src/test/java/core/basesyntax/service/ReturnHandlerTest.java b/src/test/java/core/basesyntax/service/ReturnHandlerTest.java new file mode 100644 index 0000000000..66e4277528 --- /dev/null +++ b/src/test/java/core/basesyntax/service/ReturnHandlerTest.java @@ -0,0 +1,51 @@ +package core.basesyntax.service; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import core.basesyntax.model.FruitTransaction; +import java.util.HashMap; +import java.util.Map; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class ReturnHandlerTest { + private ReturnHandler returnHandler; + + @BeforeEach + void setUp() { + returnHandler = new ReturnHandler(); + } + + @Test + void testHandleTransaction() { + Map storage = new HashMap<>(); + storage.put("apple", 10); + storage.put("banana", 5); + + FruitTransaction transaction = new FruitTransaction(FruitTransaction.Operation.RETURN, + "apple", + 3); + + returnHandler.handleTransaction(transaction, storage); + + assertEquals(13, storage.get("apple")); + + assertEquals(5, storage.get("banana")); + } + + @Test + void testHandleTransactionWhenFruitNotInStorage() { + Map storage = new HashMap<>(); + storage.put("banana", 5); + + FruitTransaction transaction = new FruitTransaction(FruitTransaction.Operation.RETURN, + "apple", + 3); + + returnHandler.handleTransaction(transaction, storage); + + assertEquals(3, storage.get("apple")); + + assertEquals(5, storage.get("banana")); + } +} diff --git a/src/test/java/core/basesyntax/service/SupplyHandlerTest.java b/src/test/java/core/basesyntax/service/SupplyHandlerTest.java new file mode 100644 index 0000000000..82aacf8bdc --- /dev/null +++ b/src/test/java/core/basesyntax/service/SupplyHandlerTest.java @@ -0,0 +1,49 @@ +package core.basesyntax.service; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import core.basesyntax.model.FruitTransaction; +import java.util.HashMap; +import java.util.Map; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class SupplyHandlerTest { + private SupplyHandler supplyHandler; + private Map storage; + + @BeforeEach + void setUp() { + supplyHandler = new SupplyHandler(); + storage = new HashMap<>(); + } + + @Test + void testHandleTransaction() { + String fruit = "apple"; + int quantity = 10; + + FruitTransaction transaction = new FruitTransaction(FruitTransaction.Operation.SUPPLY, + fruit, + quantity); + supplyHandler.handleTransaction(transaction, storage); + + assertEquals(quantity, storage.getOrDefault(fruit, 0)); + } + + @Test + void testHandleTransactionForExistingFruit() { + String fruit = "banana"; + int intialQuantity = 5; + int supllyQuantity = 10; + + storage.put(fruit, intialQuantity); + + FruitTransaction transaction = new FruitTransaction(FruitTransaction.Operation.SUPPLY, + fruit, + supllyQuantity); + supplyHandler.handleTransaction(transaction, storage); + + assertEquals(intialQuantity + supllyQuantity, storage.getOrDefault(fruit, 0)); + } +} diff --git a/tempFile.txt b/tempFile.txt new file mode 100644 index 0000000000..0c27552dec --- /dev/null +++ b/tempFile.txt @@ -0,0 +1 @@ +This is a test text. \ No newline at end of file diff --git a/test-output.txt b/test-output.txt new file mode 100644 index 0000000000..7d957d0b4a --- /dev/null +++ b/test-output.txt @@ -0,0 +1 @@ +This is a test data \ No newline at end of file