From 84be21c41e670c25b53162f188997fc4aca53650 Mon Sep 17 00:00:00 2001 From: HSoreide <sofie.scisly@gmail.com> Date: Mon, 13 Mar 2023 19:45:08 +0100 Subject: [PATCH] Write unit tests for the Recipe class --- .../idatt1002/demo/data/recipes/Recipe.java | 62 +++++++--- .../demo/data/recipes/RecipeTest.java | 117 ++++++++++++++++++ 2 files changed, 163 insertions(+), 16 deletions(-) create mode 100644 src/test/java/no/ntnu/idatt1002/demo/data/recipes/RecipeTest.java diff --git a/src/main/java/no/ntnu/idatt1002/demo/data/recipes/Recipe.java b/src/main/java/no/ntnu/idatt1002/demo/data/recipes/Recipe.java index 318534cc..dd6330f1 100644 --- a/src/main/java/no/ntnu/idatt1002/demo/data/recipes/Recipe.java +++ b/src/main/java/no/ntnu/idatt1002/demo/data/recipes/Recipe.java @@ -38,25 +38,49 @@ public class Recipe { return ingredientList; } - public void setIngredientList(List<RecipeIngredient> ingredientList) { - this.ingredientList = ingredientList; - } - public String getInstructions() { return instructions; } public void setInstructions(String instructions) { + if(instructions.isBlank()) { + throw new IllegalArgumentException("The recipe instructions cannot be left blank."); + } this.instructions = instructions; } - public void addIngredient(RecipeIngredient ingredient) { - // Remove old ingredient if it is the same type as added. Replace. - this.ingredientList.add(ingredient); - } - public void addIngredients(ArrayList<RecipeIngredient> ingredients) { + /* public void addIngredients(ArrayList<RecipeIngredient> ingredients) { ingredients.forEach((ingredient) -> this.ingredientList.add(ingredient)); + }*/ + + //TODO: Make interface for "collects ingredients" and do deep copy. + + public RecipeIngredient getIngredient(FoodItem ingredientType) { + if(ingredientType == null) return null; + return this.getIngredientList().stream() + .filter((ingredient) -> ingredient.getFoodType() == ingredientType) + .findFirst().orElse(null); + } + + + public boolean addIngredient(FoodItem ingredientType, double amount, MeasuringUnit unit) { + if(ingredientList.stream().anyMatch((ingredient) -> ingredient.getFoodType() == ingredientType)) { + try { + getIngredient(ingredientType).setAmount(amount); + getIngredient(ingredientType).setUnit(unit); + + } catch (IllegalArgumentException e) { + return false; + } + } else { + try { + this.ingredientList.add(new RecipeIngredient(ingredientType, amount, unit)); + } catch (IllegalArgumentException e) { + return false; + } + } + return true; } /** @@ -65,13 +89,19 @@ public class Recipe { */ public void updateIngredientStatus(IngredientsAtHand ingredientsAtHand) { // Will need a supporting class for converting between units to be accurate. - ingredientList.stream().forEach((inRecipe) -> { - ingredientsAtHand.getIngredientsAtHand().stream().forEach((atHand) -> { - if(inRecipe.getFoodType() == atHand.getFoodType()) { - inRecipe.setAtHand(true); - } - }); - }); + if(ingredientsAtHand == null) { + throw new NullPointerException("The ingredients at hand object must exist"); + } else if (ingredientsAtHand.getIngredientsAtHand().size() < 1) { + throw new IllegalArgumentException("The collection of ingredients at hand is empty."); + } else { + ingredientList.forEach((inRecipe) -> { + ingredientsAtHand.getIngredientsAtHand().forEach((atHand) -> { + if(inRecipe.getFoodType() == atHand.getFoodType()) { + inRecipe.setAtHand(true); + } + }); + }); + } } @Override diff --git a/src/test/java/no/ntnu/idatt1002/demo/data/recipes/RecipeTest.java b/src/test/java/no/ntnu/idatt1002/demo/data/recipes/RecipeTest.java new file mode 100644 index 00000000..46d49557 --- /dev/null +++ b/src/test/java/no/ntnu/idatt1002/demo/data/recipes/RecipeTest.java @@ -0,0 +1,117 @@ +package no.ntnu.idatt1002.demo.data.recipes; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class RecipeTest { + + Recipe recipe; + + @BeforeEach + void beforeEach() { + recipe = new Recipe("Meat, cheese and potatoes", "Instructions"); + + recipe.addIngredient(FoodItem.MINCED_MEAT, 500, MeasuringUnit.GR); + recipe.addIngredient(FoodItem.POTATO, 750, MeasuringUnit.GR); + recipe.addIngredient(FoodItem.YELLOW_CHEESE, 2, MeasuringUnit.DL); + + } + + @Test + @DisplayName("Constructor creates Recipe successfully.") + void constructorCreatesRecipe() { + assertEquals(recipe, new Recipe("Meat, cheese and potatoes", "Instructions")); + // Recipes are equal if name and Instructions are equal. + } + + @Test + @DisplayName("Constructor throws exception for empty name or instruction.") + void constructorThrowsException() { + assertThrows(IllegalArgumentException.class, () -> new Recipe("", "Instructions")); + assertThrows(IllegalArgumentException.class, () -> new Recipe("Name", "")); + + } + + @Test + @DisplayName("Can change name of recipe successfully.") + void setNameSuccessfully() { + String newName = "Meat and cheese"; + recipe.setName(newName); + assertEquals(newName, recipe.getName()); + } + + @Test + @DisplayName("Throws exception when name set to empty string.") + void setNameEmptyThrowsException() { + assertThrows(IllegalArgumentException.class, () -> recipe.setName(" ")); + } + + @Test + @DisplayName("Can change instructions of recipe successfully.") + void setInstructionsSuccessfully() { + String newInstruction = "New instructions"; + recipe.setInstructions(newInstruction); + assertEquals(newInstruction, recipe.getInstructions()); + } + + @Test + @DisplayName("Throws exception when Instructions set to empty string.") + void setInstructionsEmptyThrowsException() { + assertThrows(IllegalArgumentException.class, () -> recipe.setInstructions("")); + } + + + @Test + @DisplayName("Ingredient is added to recipe successfully.") + void addNewIngredient() { + int ingredientsInRecipe = recipe.getIngredientList().size(); + assertTrue(recipe.addIngredient(FoodItem.LEMON, 1, MeasuringUnit.PC)); + assertEquals(ingredientsInRecipe + 1, recipe.getIngredientList().size()); + } + + @Test + @DisplayName("Ingredient already in recipe does not alter and returns true.") + void addAlreadyIncludedIngredient() { + int ingredientsInRecipe = recipe.getIngredientList().size(); + assertTrue(recipe.addIngredient(FoodItem.MINCED_MEAT, 500, MeasuringUnit.GR)); + assertEquals(ingredientsInRecipe, recipe.getIngredientList().size()); + } + + @Test + @DisplayName("Invalid ingredient change is not made and false is returned.") + void addInvalidIngredientReturnsFalse() { + int ingredientsInRecipe = recipe.getIngredientList().size(); + assertFalse(recipe.addIngredient(null, 500, MeasuringUnit.GR)); + assertEquals(ingredientsInRecipe, recipe.getIngredientList().size()); + } + + + @Test + @DisplayName("Updating ingredient status works as expected.") + void updateIngredientStatus() { + IngredientsAtHand inFridge = new IngredientsAtHand(); + inFridge.addIngredient(new Ingredient(FoodItem.MINCED_MEAT, 400, MeasuringUnit.GR)); + inFridge.addIngredient(new Ingredient(FoodItem.YELLOW_CHEESE, 500, MeasuringUnit.GR)); + + + recipe.getIngredientList().forEach((ingredient) -> assertFalse(ingredient.isAtHand())); + recipe.updateIngredientStatus(inFridge); + + assertTrue(recipe.getIngredient(FoodItem.MINCED_MEAT).isAtHand()); + assertTrue(recipe.getIngredient(FoodItem.YELLOW_CHEESE).isAtHand()); + assertFalse(recipe.getIngredient(FoodItem.POTATO).isAtHand()); + } + + @Test + @DisplayName("Update of ingredient status based on empty or null ingredients at hand collection.") + void nullOrEmptyIngredientsAtHand() { + IngredientsAtHand emptyFridge = new IngredientsAtHand(); + + assertThrows(NullPointerException.class, () -> recipe.updateIngredientStatus(null)); + assertThrows(IllegalArgumentException.class, () -> recipe.updateIngredientStatus(emptyFridge)); + } + +} \ No newline at end of file -- GitLab