diff --git a/specification/README.md b/specification/README.md index a72e253d7..bb95097e3 100644 --- a/specification/README.md +++ b/specification/README.md @@ -31,7 +31,7 @@ Use the Specification pattern when Real world example -> There is a pool of different creatures and we often need to select some subset of them. We can write our search specification such as "creatures that can fly" and give it to the party that will perform the filtering. +> There is a pool of different creatures and we often need to select some subset of them. We can write our search specification such as "creatures that can fly" or "creatures heavier than 500 kilograms" and give it to the party that will perform the filtering. In Plain Words @@ -43,7 +43,8 @@ Wikipedia says **Programmatic Example** -If we look at our creature pool example from above, we have a set of creatures with certain properties. +If we look at our creature pool example from above, we have a set of creatures with certain properties.\ +Those properties can be part of a pre-defined, limited set (represented here by the enums Size, Movement and Color); but they can also be discrete (e.g. the mass of a Creature). In this case, it is more appropriate to use what we call "parameterized specification", where the property value can be given as an argument when the Creature is created, allowing for more flexibility. ```java public interface Creature { @@ -51,6 +52,7 @@ public interface Creature { Size getSize(); Movement getMovement(); Color getColor(); + Mass getMass(); } ``` @@ -60,7 +62,7 @@ And dragon implementation looks like this. public class Dragon extends AbstractCreature { public Dragon() { - super("Dragon", Size.LARGE, Movement.FLYING, Color.RED); + super("Dragon", Size.LARGE, Movement.FLYING, Color.RED, new Mass(39300.0)); } } ``` @@ -83,6 +85,24 @@ public class MovementSelector implements Predicate { } ``` +On the other hand, we selecting creatures heavier than a chosen amount, we use MassGreaterThanSelector. + +```java +public class MassGreaterThanSelector implements Predicate { + + private final Mass mass; + + public MassGreaterThanSelector(double mass) { + this.mass = new Mass(mass); + } + + @Override + public boolean test(Creature t) { + return t.getMass().greaterThan(mass); + } +} +``` + With these building blocks in place, we can perform a search for red and flying creatures like this. ```java @@ -90,6 +110,13 @@ With these building blocks in place, we can perform a search for red and flying .filter(new ColorSelector(Color.RED).and(new MovementSelector(Movement.FLYING))).collect(Collectors.toList()); ``` +But we could also use our paramterized selector like this. + +```java + List heavyCreatures = creatures.stream() + .filter(new MassGreaterThanSelector(500.0).collect(Collectors.toList()); +``` + ## Related patterns * Repository diff --git a/specification/etc/specification.ucls b/specification/etc/specification.ucls index 2edbbed0c..54b08cc41 100644 --- a/specification/etc/specification.ucls +++ b/specification/etc/specification.ucls @@ -117,7 +117,7 @@ - + @@ -126,7 +126,7 @@ - + @@ -186,13 +186,13 @@ - - + + - - - - + + + + @@ -202,7 +202,7 @@ - + diff --git a/specification/src/main/java/com/iluwatar/specification/app/App.java b/specification/src/main/java/com/iluwatar/specification/app/App.java index 8ca7283c9..c1ff8211e 100644 --- a/specification/src/main/java/com/iluwatar/specification/app/App.java +++ b/specification/src/main/java/com/iluwatar/specification/app/App.java @@ -31,8 +31,11 @@ import com.iluwatar.specification.creature.Octopus; import com.iluwatar.specification.creature.Shark; import com.iluwatar.specification.creature.Troll; import com.iluwatar.specification.property.Color; +import com.iluwatar.specification.property.Mass; import com.iluwatar.specification.property.Movement; import com.iluwatar.specification.selector.ColorSelector; +import com.iluwatar.specification.selector.MassGreaterThanSelector; +import com.iluwatar.specification.selector.MassSmallerThanOrEqSelector; import com.iluwatar.specification.selector.MovementSelector; import java.util.List; import java.util.stream.Collectors; @@ -51,7 +54,7 @@ import org.slf4j.LoggerFactory; *

http://martinfowler.com/apsupp/spec.pdf

*/ public class App { - + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); /** @@ -61,6 +64,8 @@ public class App { // initialize creatures list List creatures = List.of(new Goblin(), new Octopus(), new Dragon(), new Shark(), new Troll(), new KillerBee()); + // so-called "hard-coded" specification + LOGGER.info("Demonstrating hard-coded specification :"); // find all walking creatures LOGGER.info("Find all walking creatures"); List walkingCreatures = @@ -79,5 +84,19 @@ public class App { .filter(new ColorSelector(Color.RED).and(new MovementSelector(Movement.FLYING))) .collect(Collectors.toList()); redAndFlyingCreatures.forEach(c -> LOGGER.info(c.toString())); + // so-called "parameterized" specification + LOGGER.info("Demonstrating parameterized specification :"); + // find all creatures heavier than 500kg + LOGGER.info("Find all creatures heavier than 600kg"); + List heavyCreatures = + creatures.stream().filter(new MassGreaterThanSelector(600.0)) + .collect(Collectors.toList()); + heavyCreatures.forEach(c -> LOGGER.info(c.toString())); + // find all creatures heavier than 500kg + LOGGER.info("Find all creatures lighter than or weighing exactly 500kg"); + List lightCreatures = + creatures.stream().filter(new MassSmallerThanOrEqSelector(500.0)) + .collect(Collectors.toList()); + lightCreatures.forEach(c -> LOGGER.info(c.toString())); } } diff --git a/specification/src/main/java/com/iluwatar/specification/creature/AbstractCreature.java b/specification/src/main/java/com/iluwatar/specification/creature/AbstractCreature.java index de7a41417..6b359d8ac 100644 --- a/specification/src/main/java/com/iluwatar/specification/creature/AbstractCreature.java +++ b/specification/src/main/java/com/iluwatar/specification/creature/AbstractCreature.java @@ -24,6 +24,7 @@ package com.iluwatar.specification.creature; import com.iluwatar.specification.property.Color; +import com.iluwatar.specification.property.Mass; import com.iluwatar.specification.property.Movement; import com.iluwatar.specification.property.Size; @@ -36,20 +37,23 @@ public abstract class AbstractCreature implements Creature { private Size size; private Movement movement; private Color color; + private Mass mass; /** * Constructor. */ - public AbstractCreature(String name, Size size, Movement movement, Color color) { + public AbstractCreature(String name, Size size, Movement movement, Color color, Mass mass) { this.name = name; this.size = size; this.movement = movement; this.color = color; + this.mass = mass; } @Override public String toString() { - return String.format("%s [size=%s, movement=%s, color=%s]", name, size, movement, color); + return String.format("%s [size=%s, movement=%s, color=%s, mass=%s]", + name, size, movement, color, mass); } @Override @@ -71,4 +75,9 @@ public abstract class AbstractCreature implements Creature { public Color getColor() { return color; } + + @Override + public Mass getMass() { + return mass; + } } diff --git a/specification/src/main/java/com/iluwatar/specification/creature/Creature.java b/specification/src/main/java/com/iluwatar/specification/creature/Creature.java index 3f8ccdfdb..2eb41a6dc 100644 --- a/specification/src/main/java/com/iluwatar/specification/creature/Creature.java +++ b/specification/src/main/java/com/iluwatar/specification/creature/Creature.java @@ -24,6 +24,7 @@ package com.iluwatar.specification.creature; import com.iluwatar.specification.property.Color; +import com.iluwatar.specification.property.Mass; import com.iluwatar.specification.property.Movement; import com.iluwatar.specification.property.Size; @@ -39,4 +40,6 @@ public interface Creature { Movement getMovement(); Color getColor(); + + Mass getMass(); } diff --git a/specification/src/main/java/com/iluwatar/specification/creature/Dragon.java b/specification/src/main/java/com/iluwatar/specification/creature/Dragon.java index d4f5a7f23..937bd5497 100644 --- a/specification/src/main/java/com/iluwatar/specification/creature/Dragon.java +++ b/specification/src/main/java/com/iluwatar/specification/creature/Dragon.java @@ -24,6 +24,7 @@ package com.iluwatar.specification.creature; import com.iluwatar.specification.property.Color; +import com.iluwatar.specification.property.Mass; import com.iluwatar.specification.property.Movement; import com.iluwatar.specification.property.Size; @@ -33,6 +34,10 @@ import com.iluwatar.specification.property.Size; public class Dragon extends AbstractCreature { public Dragon() { - super("Dragon", Size.LARGE, Movement.FLYING, Color.RED); + this(new Mass(39300.0)); + } + + public Dragon(Mass mass) { + super("Dragon", Size.LARGE, Movement.FLYING, Color.RED, mass); } } diff --git a/specification/src/main/java/com/iluwatar/specification/creature/Goblin.java b/specification/src/main/java/com/iluwatar/specification/creature/Goblin.java index 0b145b737..7b173d580 100644 --- a/specification/src/main/java/com/iluwatar/specification/creature/Goblin.java +++ b/specification/src/main/java/com/iluwatar/specification/creature/Goblin.java @@ -24,6 +24,7 @@ package com.iluwatar.specification.creature; import com.iluwatar.specification.property.Color; +import com.iluwatar.specification.property.Mass; import com.iluwatar.specification.property.Movement; import com.iluwatar.specification.property.Size; @@ -33,6 +34,10 @@ import com.iluwatar.specification.property.Size; public class Goblin extends AbstractCreature { public Goblin() { - super("Goblin", Size.SMALL, Movement.WALKING, Color.GREEN); + this(new Mass(30.0)); + } + + public Goblin(Mass mass) { + super("Goblin", Size.SMALL, Movement.WALKING, Color.GREEN, mass); } } diff --git a/specification/src/main/java/com/iluwatar/specification/creature/KillerBee.java b/specification/src/main/java/com/iluwatar/specification/creature/KillerBee.java index 77f32c9f4..2b35714fc 100644 --- a/specification/src/main/java/com/iluwatar/specification/creature/KillerBee.java +++ b/specification/src/main/java/com/iluwatar/specification/creature/KillerBee.java @@ -24,6 +24,7 @@ package com.iluwatar.specification.creature; import com.iluwatar.specification.property.Color; +import com.iluwatar.specification.property.Mass; import com.iluwatar.specification.property.Movement; import com.iluwatar.specification.property.Size; @@ -33,6 +34,10 @@ import com.iluwatar.specification.property.Size; public class KillerBee extends AbstractCreature { public KillerBee() { - super("KillerBee", Size.SMALL, Movement.FLYING, Color.LIGHT); + this(new Mass(6.7)); + } + + public KillerBee(Mass mass) { + super("KillerBee", Size.SMALL, Movement.FLYING, Color.LIGHT, mass); } } diff --git a/specification/src/main/java/com/iluwatar/specification/creature/Octopus.java b/specification/src/main/java/com/iluwatar/specification/creature/Octopus.java index 6958f7fbd..f516a6dc5 100644 --- a/specification/src/main/java/com/iluwatar/specification/creature/Octopus.java +++ b/specification/src/main/java/com/iluwatar/specification/creature/Octopus.java @@ -24,6 +24,7 @@ package com.iluwatar.specification.creature; import com.iluwatar.specification.property.Color; +import com.iluwatar.specification.property.Mass; import com.iluwatar.specification.property.Movement; import com.iluwatar.specification.property.Size; @@ -33,6 +34,10 @@ import com.iluwatar.specification.property.Size; public class Octopus extends AbstractCreature { public Octopus() { - super("Octopus", Size.NORMAL, Movement.SWIMMING, Color.DARK); + this(new Mass(12.0)); + } + + public Octopus(Mass mass) { + super("Octopus", Size.NORMAL, Movement.SWIMMING, Color.DARK, mass); } } diff --git a/specification/src/main/java/com/iluwatar/specification/creature/Shark.java b/specification/src/main/java/com/iluwatar/specification/creature/Shark.java index b9e161da4..8788e85d7 100644 --- a/specification/src/main/java/com/iluwatar/specification/creature/Shark.java +++ b/specification/src/main/java/com/iluwatar/specification/creature/Shark.java @@ -24,6 +24,7 @@ package com.iluwatar.specification.creature; import com.iluwatar.specification.property.Color; +import com.iluwatar.specification.property.Mass; import com.iluwatar.specification.property.Movement; import com.iluwatar.specification.property.Size; @@ -33,6 +34,10 @@ import com.iluwatar.specification.property.Size; public class Shark extends AbstractCreature { public Shark() { - super("Shark", Size.NORMAL, Movement.SWIMMING, Color.LIGHT); + this(new Mass(500.0)); + } + + public Shark(Mass mass) { + super("Shark", Size.NORMAL, Movement.SWIMMING, Color.LIGHT, mass); } } diff --git a/specification/src/main/java/com/iluwatar/specification/creature/Troll.java b/specification/src/main/java/com/iluwatar/specification/creature/Troll.java index 3f416bdd1..addcb94b6 100644 --- a/specification/src/main/java/com/iluwatar/specification/creature/Troll.java +++ b/specification/src/main/java/com/iluwatar/specification/creature/Troll.java @@ -24,6 +24,7 @@ package com.iluwatar.specification.creature; import com.iluwatar.specification.property.Color; +import com.iluwatar.specification.property.Mass; import com.iluwatar.specification.property.Movement; import com.iluwatar.specification.property.Size; @@ -33,6 +34,10 @@ import com.iluwatar.specification.property.Size; public class Troll extends AbstractCreature { public Troll() { - super("Troll", Size.LARGE, Movement.WALKING, Color.DARK); + this(new Mass(4000.0)); + } + + public Troll(Mass mass) { + super("Troll", Size.LARGE, Movement.WALKING, Color.DARK, mass); } } diff --git a/specification/src/main/java/com/iluwatar/specification/property/Color.java b/specification/src/main/java/com/iluwatar/specification/property/Color.java index 00f7007ff..6e96b5813 100644 --- a/specification/src/main/java/com/iluwatar/specification/property/Color.java +++ b/specification/src/main/java/com/iluwatar/specification/property/Color.java @@ -24,7 +24,7 @@ package com.iluwatar.specification.property; /** - *

Color property.

+ * Color property. */ public enum Color { diff --git a/specification/src/main/java/com/iluwatar/specification/property/Mass.java b/specification/src/main/java/com/iluwatar/specification/property/Mass.java new file mode 100644 index 000000000..6be1edb33 --- /dev/null +++ b/specification/src/main/java/com/iluwatar/specification/property/Mass.java @@ -0,0 +1,65 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.specification.property; + +/** Mass property. */ +public class Mass { + + private double value; + private String title; + + public Mass(double value) { + this.value = value; + this.title = value + "kg"; // Implicit call to Double.toString(value) + } + + public final boolean greaterThan(Mass other) { + return this.value > other.value; + } + + public final boolean smallerThan(Mass other) { + return this.value < other.value; + } + + public final boolean greaterThanOrEq(Mass other) { + return this.value >= other.value; + } + + public final boolean smallerThanOrEq(Mass other) { + return this.value <= other.value; + } + + @Override + public String toString() { + return title; + } + + @Override + public final boolean equals(Object obj) { + if (!(obj instanceof Mass)) { + return false; + } + return ((Mass) obj).value == this.value; + } +} diff --git a/specification/src/main/java/com/iluwatar/specification/selector/MassGreaterThanSelector.java b/specification/src/main/java/com/iluwatar/specification/selector/MassGreaterThanSelector.java new file mode 100644 index 000000000..d613e6a08 --- /dev/null +++ b/specification/src/main/java/com/iluwatar/specification/selector/MassGreaterThanSelector.java @@ -0,0 +1,44 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.specification.selector; + +import com.iluwatar.specification.creature.Creature; +import com.iluwatar.specification.property.Mass; +import java.util.function.Predicate; + +/** Mass selector for values greater than the parameter. */ +public class MassGreaterThanSelector implements Predicate { + + private final Mass mass; + + /** The use of a double as a parameter will spare some typing when instantiating this class. */ + public MassGreaterThanSelector(double mass) { + this.mass = new Mass(mass); + } + + @Override + public boolean test(Creature t) { + return t.getMass().greaterThan(mass); + } +} diff --git a/specification/src/main/java/com/iluwatar/specification/selector/MassSmallerThanOrEqSelector.java b/specification/src/main/java/com/iluwatar/specification/selector/MassSmallerThanOrEqSelector.java new file mode 100644 index 000000000..8a6a9f80e --- /dev/null +++ b/specification/src/main/java/com/iluwatar/specification/selector/MassSmallerThanOrEqSelector.java @@ -0,0 +1,44 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.specification.selector; + +import com.iluwatar.specification.creature.Creature; +import com.iluwatar.specification.property.Mass; +import java.util.function.Predicate; + +/** Mass selector for values smaller or equal to the parameter. */ +public class MassSmallerThanOrEqSelector implements Predicate { + + private final Mass mass; + + /** The use of a double as a parameter will spare some typing when instantiating this class. */ + public MassSmallerThanOrEqSelector(double mass) { + this.mass = new Mass(mass); + } + + @Override + public boolean test(Creature t) { + return t.getMass().smallerThanOrEq(mass); + } +} diff --git a/specification/src/test/java/com/iluwatar/specification/creature/CreatureTest.java b/specification/src/test/java/com/iluwatar/specification/creature/CreatureTest.java index 26ff4c1ab..ecd3de27f 100644 --- a/specification/src/test/java/com/iluwatar/specification/creature/CreatureTest.java +++ b/specification/src/test/java/com/iluwatar/specification/creature/CreatureTest.java @@ -24,6 +24,7 @@ package com.iluwatar.specification.creature; import com.iluwatar.specification.property.Color; +import com.iluwatar.specification.property.Mass; import com.iluwatar.specification.property.Movement; import com.iluwatar.specification.property.Size; import org.junit.jupiter.params.ParameterizedTest; @@ -47,12 +48,12 @@ public class CreatureTest { */ public static Collection dataProvider() { return List.of( - new Object[]{new Dragon(), "Dragon", Size.LARGE, Movement.FLYING, Color.RED}, - new Object[]{new Goblin(), "Goblin", Size.SMALL, Movement.WALKING, Color.GREEN}, - new Object[]{new KillerBee(), "KillerBee", Size.SMALL, Movement.FLYING, Color.LIGHT}, - new Object[]{new Octopus(), "Octopus", Size.NORMAL, Movement.SWIMMING, Color.DARK}, - new Object[]{new Shark(), "Shark", Size.NORMAL, Movement.SWIMMING, Color.LIGHT}, - new Object[]{new Troll(), "Troll", Size.LARGE, Movement.WALKING, Color.DARK} + new Object[]{new Dragon(), "Dragon", Size.LARGE, Movement.FLYING, Color.RED, new Mass(39300.0)}, + new Object[]{new Goblin(), "Goblin", Size.SMALL, Movement.WALKING, Color.GREEN, new Mass(30.0)}, + new Object[]{new KillerBee(), "KillerBee", Size.SMALL, Movement.FLYING, Color.LIGHT, new Mass(6.7)}, + new Object[]{new Octopus(), "Octopus", Size.NORMAL, Movement.SWIMMING, Color.DARK, new Mass(12.0)}, + new Object[]{new Shark(), "Shark", Size.NORMAL, Movement.SWIMMING, Color.LIGHT, new Mass(500.0)}, + new Object[]{new Troll(), "Troll", Size.LARGE, Movement.WALKING, Color.DARK, new Mass(4000.0)} ); } @@ -82,11 +83,17 @@ public class CreatureTest { @ParameterizedTest @MethodSource("dataProvider") - public void testToString(Creature testedCreature, String name, Size size, Movement movement, Color color) { + public void testGetMass(Creature testedCreature, String name, Size size, Movement movement, Color color, Mass mass) { + assertEquals(mass, testedCreature.getMass()); + } + + @ParameterizedTest + @MethodSource("dataProvider") + public void testToString(Creature testedCreature, String name, Size size, Movement movement, Color color, Mass mass) { final String toString = testedCreature.toString(); assertNotNull(toString); assertEquals( - String.format("%s [size=%s, movement=%s, color=%s]", name, size, movement, color), + String.format("%s [size=%s, movement=%s, color=%s, mass=%s]", name, size, movement, color, mass), toString ); } diff --git a/specification/src/test/java/com/iluwatar/specification/selector/MassSelectorTest.java b/specification/src/test/java/com/iluwatar/specification/selector/MassSelectorTest.java new file mode 100644 index 000000000..eb2f4c5fe --- /dev/null +++ b/specification/src/test/java/com/iluwatar/specification/selector/MassSelectorTest.java @@ -0,0 +1,50 @@ +/* + * The MIT License + * Copyright © 2014-2019 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.specification.selector; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.iluwatar.specification.creature.Creature; +import com.iluwatar.specification.property.Mass; +import org.junit.jupiter.api.Test; + +public class MassSelectorTest { + + /** Verify if the mass selector gives the correct results */ + @Test + public void testMass() { + final Creature lightCreature = mock(Creature.class); + when(lightCreature.getMass()).thenReturn(new Mass(50.0)); + + final Creature heavyCreature = mock(Creature.class); + when(heavyCreature.getMass()).thenReturn(new Mass(2500.0)); + + final MassSmallerThanOrEqSelector lightSelector = new MassSmallerThanOrEqSelector(500.0); + assertTrue(lightSelector.test(lightCreature)); + assertFalse(lightSelector.test(heavyCreature)); + } +}