diff --git a/Java/pom.xml b/Java/pom.xml
index 5d65fa0b..e9c8f5d8 100644
--- a/Java/pom.xml
+++ b/Java/pom.xml
@@ -13,15 +13,40 @@
1.8
5.6.2
3.0.0-M4
+ 3.16.1
+ 3.10
+ 3.3.3
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons-lang3.version}
+
+
org.junit.jupiter
junit-jupiter
${junit.jupiter.version}
test
+
+
+ org.assertj
+ assertj-core
+ ${assertj-core.version}
+ test
+
+
+
+ org.mockito
+ mockito-core
+ ${mockito.version}
+ test
+
+
diff --git a/Java/src/main/java/com/gildedrose/GRItem.java b/Java/src/main/java/com/gildedrose/GRItem.java
new file mode 100644
index 00000000..8132a3b5
--- /dev/null
+++ b/Java/src/main/java/com/gildedrose/GRItem.java
@@ -0,0 +1,97 @@
+package com.gildedrose;
+
+public class GRItem {
+
+ private static final String AGED_BRIE = "Aged Brie";
+ private static final String SULFURAS = "Sulfuras, Hand of Ragnaros";
+ private static final int MAX_QUALITY = 50;
+ private static final int MIN_QUALITY = 0;
+
+ private final Item item;
+
+ public GRItem(Item item) {
+ this.item = item;
+ }
+
+ public GRItem(String name, int sellIn, int quality) {
+ this.item = new Item(name, sellIn, quality);
+ }
+
+ public String getName() {
+ return item.name;
+ }
+
+ public int getSellIn() {
+ return item.sellIn;
+ }
+
+ public int getQuality() {
+ return item.quality;
+ }
+
+ public void updateQuality() {
+ if (!item.name.equals(AGED_BRIE)
+ && !item.name.equals("Backstage passes to a TAFKAL80ETC concert")) {
+ if (item.quality > 0) {
+ if (!item.name.equals(SULFURAS)) {
+ item.quality = item.quality - 1;
+ }
+ }
+ } else {
+ if (item.quality < MAX_QUALITY) {
+ item.quality = item.quality + 1;
+
+ if (item.name.equals("Backstage passes to a TAFKAL80ETC concert")) {
+ if (item.sellIn < 11) {
+ if (item.quality < MAX_QUALITY) {
+ item.quality = item.quality + 1;
+ }
+ }
+
+ if (item.sellIn < 6) {
+ if (item.quality < MAX_QUALITY) {
+ item.quality = item.quality + 1;
+ }
+ }
+ }
+ }
+ }
+
+ if (!item.name.equals(SULFURAS)) {
+ item.sellIn = item.sellIn - 1;
+ }
+
+ if (item.sellIn < 0) {
+ if (!item.name.equals(AGED_BRIE)) {
+ if (!item.name.equals("Backstage passes to a TAFKAL80ETC concert")) {
+ if (item.quality > MIN_QUALITY) {
+ if (!item.name.equals(SULFURAS)) {
+ item.quality = item.quality - 1;
+ }
+ }
+ } else {
+ item.quality = 0;
+ }
+ } else {
+ if (item.quality < MAX_QUALITY) {
+ item.quality = item.quality + 1;
+ }
+ }
+ }
+ }
+
+ public static void validateItem(Item item) {
+ if (item.quality < GRItem.MIN_QUALITY) {
+ throw new ItemQualityIsNegativeException(item.name);
+ } else if (item.quality > GRItem.MAX_QUALITY && !item.name.equals(SULFURAS)) {
+ throw new ItemQualityExceedsMaxValueException(item.name);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "GRItem{" +
+ "item=" + item +
+ '}';
+ }
+}
diff --git a/Java/src/main/java/com/gildedrose/GildedRose.java b/Java/src/main/java/com/gildedrose/GildedRose.java
index e6feb751..3942c4de 100644
--- a/Java/src/main/java/com/gildedrose/GildedRose.java
+++ b/Java/src/main/java/com/gildedrose/GildedRose.java
@@ -1,62 +1,16 @@
package com.gildedrose;
+import java.util.Arrays;
+
class GildedRose {
Item[] items;
public GildedRose(Item[] items) {
+ Arrays.stream(items).forEach(GRItem::validateItem);
this.items = items;
}
public void updateQuality() {
- for (int i = 0; i < items.length; i++) {
- if (!items[i].name.equals("Aged Brie")
- && !items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) {
- if (items[i].quality > 0) {
- if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) {
- items[i].quality = items[i].quality - 1;
- }
- }
- } else {
- if (items[i].quality < 50) {
- items[i].quality = items[i].quality + 1;
-
- if (items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) {
- if (items[i].sellIn < 11) {
- if (items[i].quality < 50) {
- items[i].quality = items[i].quality + 1;
- }
- }
-
- if (items[i].sellIn < 6) {
- if (items[i].quality < 50) {
- items[i].quality = items[i].quality + 1;
- }
- }
- }
- }
- }
-
- if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) {
- items[i].sellIn = items[i].sellIn - 1;
- }
-
- if (items[i].sellIn < 0) {
- if (!items[i].name.equals("Aged Brie")) {
- if (!items[i].name.equals("Backstage passes to a TAFKAL80ETC concert")) {
- if (items[i].quality > 0) {
- if (!items[i].name.equals("Sulfuras, Hand of Ragnaros")) {
- items[i].quality = items[i].quality - 1;
- }
- }
- } else {
- items[i].quality = items[i].quality - items[i].quality;
- }
- } else {
- if (items[i].quality < 50) {
- items[i].quality = items[i].quality + 1;
- }
- }
- }
- }
+ Arrays.stream(items).map(GRItem::new).forEach(GRItem::updateQuality);
}
}
\ No newline at end of file
diff --git a/Java/src/main/java/com/gildedrose/Item.java b/Java/src/main/java/com/gildedrose/Item.java
index 465729ec..19634c6d 100644
--- a/Java/src/main/java/com/gildedrose/Item.java
+++ b/Java/src/main/java/com/gildedrose/Item.java
@@ -14,8 +14,8 @@ public class Item {
this.quality = quality;
}
- @Override
- public String toString() {
+ @Override
+ public String toString() {
return this.name + ", " + this.sellIn + ", " + this.quality;
}
}
diff --git a/Java/src/main/java/com/gildedrose/ItemQualityExceedsMaxValueException.java b/Java/src/main/java/com/gildedrose/ItemQualityExceedsMaxValueException.java
new file mode 100644
index 00000000..d80fbd42
--- /dev/null
+++ b/Java/src/main/java/com/gildedrose/ItemQualityExceedsMaxValueException.java
@@ -0,0 +1,8 @@
+package com.gildedrose;
+
+public class ItemQualityExceedsMaxValueException extends RuntimeException {
+
+ public ItemQualityExceedsMaxValueException(String name) {
+ super("Item '" + name + "' exceeds max value for quality ");
+ }
+}
diff --git a/Java/src/main/java/com/gildedrose/ItemQualityIsNegativeException.java b/Java/src/main/java/com/gildedrose/ItemQualityIsNegativeException.java
new file mode 100644
index 00000000..1d9bf8ff
--- /dev/null
+++ b/Java/src/main/java/com/gildedrose/ItemQualityIsNegativeException.java
@@ -0,0 +1,8 @@
+package com.gildedrose;
+
+public class ItemQualityIsNegativeException extends RuntimeException {
+
+ public ItemQualityIsNegativeException(String name) {
+ super("Item '" + name + "' has a negative quality value");
+ }
+}
diff --git a/Java/src/test/java/com/gildedrose/GRItemConstructorTest.java b/Java/src/test/java/com/gildedrose/GRItemConstructorTest.java
new file mode 100644
index 00000000..c7a20d67
--- /dev/null
+++ b/Java/src/test/java/com/gildedrose/GRItemConstructorTest.java
@@ -0,0 +1,22 @@
+package com.gildedrose;
+
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class GRItemConstructorTest {
+
+ private static final String NAME = "+5 Dexterity Vest";
+ private static final int SELL_IN = 10;
+ private static final int QUALITY = 20;
+
+ @Test
+ public void constructsCorrectly() {
+ Item item = new Item(NAME, SELL_IN, QUALITY);
+ GRItem grItem = new GRItem(item);
+
+ assertThat(grItem.getName()).isEqualTo(NAME);
+ assertThat(grItem.getSellIn()).isEqualTo(SELL_IN);
+ assertThat(grItem.getQuality()).isEqualTo(QUALITY);
+ }
+}
diff --git a/Java/src/test/java/com/gildedrose/GRItemUpdateQualityTest.java b/Java/src/test/java/com/gildedrose/GRItemUpdateQualityTest.java
new file mode 100644
index 00000000..67868dbe
--- /dev/null
+++ b/Java/src/test/java/com/gildedrose/GRItemUpdateQualityTest.java
@@ -0,0 +1,114 @@
+package com.gildedrose;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+import static org.apache.commons.lang3.RandomStringUtils.random;
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class GRItemUpdateQualityTest {
+ private static final String AGED_BRIE = "Aged Brie";
+ private static final String SULFURAS = "Sulfuras, Hand of Ragnaros";
+ private static final String BACKSTAGE_PASSES = "Backstage passes to a TAFKAL80ETC concert";
+
+ @Test
+ public void lowersTheSellInValue() {
+ GRItem item = new GRItem(random(5), 10, 20);
+ item.updateQuality();
+
+ assertThat(item.getSellIn()).isEqualTo(9);
+ }
+
+ @Test
+ public void qualityDegrades() {
+ GRItem item = new GRItem(random(5), 10, 20);
+ item.updateQuality();
+
+ assertThat(item.getQuality()).isEqualTo(19);
+ }
+
+ @Test
+ public void qualityDegradesTwiceAsFastWhenSellByDatePassed() {
+ GRItem item = new GRItem(random(5), 0, 20);
+ item.updateQuality();
+
+ assertThat(item.getQuality()).isEqualTo(18);
+ }
+
+ @Test
+ public void qualityIsNeverNegative() {
+ GRItem item = new GRItem(random(5), 10, 0);
+ item.updateQuality();
+
+ assertThat(item.getQuality()).isEqualTo(0);
+ }
+
+ @Test
+ public void qualityOfAgedBrieIncreases() {
+ GRItem item = new GRItem(AGED_BRIE, 10, 10);
+ item.updateQuality();
+
+ assertThat(item.getQuality()).isEqualTo(11);
+ }
+
+ @Test
+ public void qualityOfAgedBrieIncreasesEvenWhenSellInIsNegative() {
+ GRItem item = new GRItem(AGED_BRIE, -1, 10);
+ item.updateQuality();
+
+ assertThat(item.getQuality()).isEqualTo(12);
+ }
+
+ @Test
+ public void qualityIncreasesNeverHigherThan50() {
+ GRItem item = new GRItem(AGED_BRIE, 10, 50);
+ item.updateQuality();
+
+ assertThat(item.getQuality()).isEqualTo(50);
+ }
+
+ @ParameterizedTest(name = "with quality {0}")
+ @ValueSource(ints = {-1, 0, 1, 20, 50})
+ public void qualityOfSulfurasNeverAlters(int quality) {
+ GRItem item = new GRItem(SULFURAS, 10, quality);
+ item.updateQuality();
+
+ assertThat(item.getQuality()).isEqualTo(quality);
+ }
+
+ @Test
+ public void sellInOfSulfurasNeverAlters() {
+ GRItem item = new GRItem(SULFURAS, 10, 20);
+ item.updateQuality();
+
+ assertThat(item.getSellIn()).isEqualTo(10);
+ }
+
+ @ParameterizedTest(name = "with sellIn {0}")
+ @ValueSource(ints = {10, 9, 8, 7, 6})
+ public void qualityOfBackstagePassesIncreaseBy2WhenSellIn10DaysOrLess(int sellIn) {
+ GRItem item = new GRItem(BACKSTAGE_PASSES, sellIn, 10);
+ item.updateQuality();
+
+ assertThat(item.getQuality()).isEqualTo(12);
+ }
+
+ @ParameterizedTest(name = "with sellIn {0}")
+ @ValueSource(ints = {5, 4, 3, 2, 1})
+ public void qualityOfBackstagePassesIncreaseBy3WhenSellIn5DaysOrLess(int sellIn) {
+ GRItem item = new GRItem(BACKSTAGE_PASSES, sellIn, 10);
+ item.updateQuality();
+
+ assertThat(item.getQuality()).isEqualTo(13);
+ }
+
+ @ParameterizedTest(name = "with sellIn {0}")
+ @ValueSource(ints = {0, -1})
+ public void qualityOfBackstagePassesIsZeroAfterConcert(int sellIn) {
+ GRItem item = new GRItem(BACKSTAGE_PASSES, sellIn, 10);
+ item.updateQuality();
+
+ assertThat(item.getQuality()).isEqualTo(0);
+ }
+}
diff --git a/Java/src/test/java/com/gildedrose/GRItemValidateItemTest.java b/Java/src/test/java/com/gildedrose/GRItemValidateItemTest.java
new file mode 100644
index 00000000..957aabba
--- /dev/null
+++ b/Java/src/test/java/com/gildedrose/GRItemValidateItemTest.java
@@ -0,0 +1,33 @@
+package com.gildedrose;
+
+import org.junit.jupiter.api.Test;
+
+import static org.apache.commons.lang3.RandomStringUtils.random;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+class GRItemValidateItemTest {
+
+ private static final String SULFURAS = "Sulfuras, Hand of Ragnaros";
+
+ @Test
+ public void throwsExceptionWhenItemValueIsNegative() {
+ Item item = new Item(random(5), 10, -1);
+
+ assertThatThrownBy(() -> GRItem.validateItem(item)).isInstanceOf(ItemQualityIsNegativeException.class);
+ }
+
+ @Test
+ public void throwsExceptionWhenItemValueExceedsMaxValue() {
+ Item item = new Item(random(5), 10, 51);
+
+ assertThatThrownBy(() -> GRItem.validateItem(item)).isInstanceOf(ItemQualityExceedsMaxValueException.class);
+ }
+
+
+ @Test
+ public void doesNotThrowExceptionWhenItemValueExceedsMaxValueAndItemIsSulfuras() {
+ Item item = new Item(SULFURAS, 10, 51);
+
+ GRItem.validateItem(item);
+ }
+}
\ No newline at end of file
diff --git a/Java/src/test/java/com/gildedrose/GildedRoseTest.java b/Java/src/test/java/com/gildedrose/GildedRoseTest.java
deleted file mode 100644
index 8ae29eec..00000000
--- a/Java/src/test/java/com/gildedrose/GildedRoseTest.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.gildedrose;
-
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-class GildedRoseTest {
-
- @Test
- void foo() {
- Item[] items = new Item[] { new Item("foo", 0, 0) };
- GildedRose app = new GildedRose(items);
- app.updateQuality();
- assertEquals("fixme", app.items[0].name);
- }
-
-}
diff --git a/Java/src/test/java/com/gildedrose/GildedRoseUpdateQualityTest.java b/Java/src/test/java/com/gildedrose/GildedRoseUpdateQualityTest.java
new file mode 100644
index 00000000..cd7ccd2d
--- /dev/null
+++ b/Java/src/test/java/com/gildedrose/GildedRoseUpdateQualityTest.java
@@ -0,0 +1,34 @@
+package com.gildedrose;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+
+import static org.apache.commons.lang3.RandomStringUtils.random;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class GildedRoseUpdateQualityTest {
+
+ private GildedRose gildedRose;
+
+ @BeforeEach
+ void setUp() {
+ Item[] items = new Item[]{
+ new Item("+5 Dexterity Vest", 10, 20),
+ new Item("Aged Brie", 2, 0),
+ new Item("Elixir of the Mongoose", 5, 7),
+ new Item("Backstage passes to a TAFKAL80ETC concert", 15, 20),
+ };
+
+ gildedRose = new GildedRose(items);
+ }
+
+ @Test
+ public void updatesTheQualityOfAllItems() {
+ assertThat(gildedRose.items).extracting(i -> i.quality).containsExactly(20, 0, 7, 20);
+ gildedRose.updateQuality();
+ assertThat(gildedRose.items).extracting(i -> i.quality).containsExactly(19, 1, 6, 21);
+ }
+
+}
diff --git a/Java/src/test/java/com/gildedrose/GuildedRoseConstructorTest.java b/Java/src/test/java/com/gildedrose/GuildedRoseConstructorTest.java
new file mode 100644
index 00000000..fdb42eca
--- /dev/null
+++ b/Java/src/test/java/com/gildedrose/GuildedRoseConstructorTest.java
@@ -0,0 +1,17 @@
+package com.gildedrose;
+
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+public class GuildedRoseConstructorTest {
+
+ @Test
+ public void validatesInitialItemQualities() {
+ Item[] items = new Item[]{
+ new Item("+5 Dexterity Vest", 10, -1)
+ };
+
+ assertThatThrownBy(() -> new GildedRose(items)).isInstanceOf(ItemQualityIsNegativeException.class);
+ }
+}