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