Merge pull request #312 from fluxw42/master
Add proper unit tests for chain, bridge and builder pattern #293
This commit is contained in:
commit
d7dd8d42af
@ -14,5 +14,9 @@
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
@ -0,0 +1,33 @@
|
||||
package com.iluwatar.bridge;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.internal.verification.VerificationModeFactory.times;
|
||||
|
||||
/**
|
||||
* Date: 12/6/15 - 11:15 PM
|
||||
*
|
||||
* @author Jeroen Meulemeester
|
||||
*/
|
||||
public class BlindingMagicWeaponTest extends MagicWeaponTest {
|
||||
|
||||
/**
|
||||
* Invoke all possible actions on the weapon and check if the actions are executed on the actual
|
||||
* underlying weapon implementation.
|
||||
*/
|
||||
@Test
|
||||
public void testExcalibur() throws Exception {
|
||||
final Excalibur excalibur = spy(new Excalibur());
|
||||
final BlindingMagicWeapon blindingMagicWeapon = new BlindingMagicWeapon(excalibur);
|
||||
|
||||
testBasicWeaponActions(blindingMagicWeapon, excalibur);
|
||||
|
||||
blindingMagicWeapon.blind();
|
||||
verify(excalibur, times(1)).blindImp();
|
||||
verifyNoMoreInteractions(excalibur);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package com.iluwatar.bridge;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.internal.verification.VerificationModeFactory.times;
|
||||
|
||||
/**
|
||||
* Date: 12/6/15 - 11:26 PM
|
||||
*
|
||||
* @author Jeroen Meulemeester
|
||||
*/
|
||||
public class FlyingMagicWeaponTest extends MagicWeaponTest {
|
||||
|
||||
/**
|
||||
* Invoke all possible actions on the weapon and check if the actions are executed on the actual
|
||||
* underlying weapon implementation.
|
||||
*/
|
||||
@Test
|
||||
public void testMjollnir() throws Exception {
|
||||
final Mjollnir mjollnir = spy(new Mjollnir());
|
||||
final FlyingMagicWeapon flyingMagicWeapon = new FlyingMagicWeapon(mjollnir);
|
||||
|
||||
testBasicWeaponActions(flyingMagicWeapon, mjollnir);
|
||||
|
||||
flyingMagicWeapon.fly();
|
||||
verify(mjollnir, times(1)).flyImp();
|
||||
verifyNoMoreInteractions(mjollnir);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package com.iluwatar.bridge;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.internal.verification.VerificationModeFactory.times;
|
||||
|
||||
/**
|
||||
* Date: 12/6/15 - 11:28 PM
|
||||
*
|
||||
* @author Jeroen Meulemeester
|
||||
*/
|
||||
public abstract class MagicWeaponTest {
|
||||
|
||||
/**
|
||||
* Invoke the basic actions of the given weapon, and test if the underlying weapon implementation
|
||||
* is invoked
|
||||
*
|
||||
* @param weaponImpl The spied weapon implementation where actions are bridged to
|
||||
* @param weapon The weapon, handled by the app
|
||||
*/
|
||||
protected final void testBasicWeaponActions(final MagicWeapon weapon,
|
||||
final MagicWeaponImpl weaponImpl) {
|
||||
assertNotNull(weapon);
|
||||
assertNotNull(weaponImpl);
|
||||
assertNotNull(weapon.getImp());
|
||||
|
||||
weapon.swing();
|
||||
verify(weaponImpl, times(1)).swingImp();
|
||||
verifyNoMoreInteractions(weaponImpl);
|
||||
|
||||
weapon.wield();
|
||||
verify(weaponImpl, times(1)).wieldImp();
|
||||
verifyNoMoreInteractions(weaponImpl);
|
||||
|
||||
weapon.unwield();
|
||||
verify(weaponImpl, times(1)).unwieldImp();
|
||||
verifyNoMoreInteractions(weaponImpl);
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package com.iluwatar.bridge;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.internal.verification.VerificationModeFactory.times;
|
||||
|
||||
/**
|
||||
* Date: 12/6/15 - 11:43 PM
|
||||
*
|
||||
* @author Jeroen Meulemeester
|
||||
*/
|
||||
public class SoulEatingMagicWeaponTest extends MagicWeaponTest {
|
||||
|
||||
/**
|
||||
* Invoke all possible actions on the weapon and check if the actions are executed on the actual
|
||||
* underlying weapon implementation.
|
||||
*/
|
||||
@Test
|
||||
public void testStormBringer() throws Exception {
|
||||
final Stormbringer stormbringer = spy(new Stormbringer());
|
||||
final SoulEatingMagicWeapon soulEatingMagicWeapon = new SoulEatingMagicWeapon(stormbringer);
|
||||
|
||||
testBasicWeaponActions(soulEatingMagicWeapon, stormbringer);
|
||||
|
||||
soulEatingMagicWeapon.eatSoul();
|
||||
verify(stormbringer, times(1)).eatSoulImp();
|
||||
verifyNoMoreInteractions(stormbringer);
|
||||
}
|
||||
|
||||
}
|
56
builder/src/test/java/com/iluwatar/builder/HeroTest.java
Normal file
56
builder/src/test/java/com/iluwatar/builder/HeroTest.java
Normal file
@ -0,0 +1,56 @@
|
||||
package com.iluwatar.builder;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
/**
|
||||
* Date: 12/6/15 - 11:01 PM
|
||||
*
|
||||
* @author Jeroen Meulemeester
|
||||
*/
|
||||
public class HeroTest {
|
||||
|
||||
/**
|
||||
* Test if we get the expected exception when trying to create a hero without a profession
|
||||
*/
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testMissingProfession() throws Exception {
|
||||
new Hero.HeroBuilder(null, "Sir without a job");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if we get the expected exception when trying to create a hero without a name
|
||||
*/
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testMissingName() throws Exception {
|
||||
new Hero.HeroBuilder(Profession.THIEF, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the hero build by the builder has the correct attributes, as requested
|
||||
*/
|
||||
@Test
|
||||
public void testBuildHero() throws Exception {
|
||||
final String heroName = "Sir Lancelot";
|
||||
|
||||
final Hero hero = new Hero.HeroBuilder(Profession.WARRIOR, heroName)
|
||||
.withArmor(Armor.CHAIN_MAIL)
|
||||
.withWeapon(Weapon.SWORD)
|
||||
.withHairType(HairType.LONG_CURLY)
|
||||
.withHairColor(HairColor.BLOND)
|
||||
.build();
|
||||
|
||||
assertNotNull(hero);
|
||||
assertNotNull(hero.toString());
|
||||
assertEquals(Profession.WARRIOR, hero.getProfession());
|
||||
assertEquals(heroName, hero.getName());
|
||||
assertEquals(Armor.CHAIN_MAIL, hero.getArmor());
|
||||
assertEquals(Weapon.SWORD, hero.getWeapon());
|
||||
assertEquals(HairType.LONG_CURLY, hero.getHairType());
|
||||
assertEquals(HairColor.BLOND, hero.getHairColor());
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -15,6 +15,7 @@ public class OrcCommander extends RequestHandler {
|
||||
public void handleRequest(Request req) {
|
||||
if (req.getRequestType().equals(RequestType.DEFEND_CASTLE)) {
|
||||
printHandling(req);
|
||||
req.markHandled();
|
||||
} else {
|
||||
super.handleRequest(req);
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ public class OrcOfficer extends RequestHandler {
|
||||
public void handleRequest(Request req) {
|
||||
if (req.getRequestType().equals(RequestType.TORTURE_PRISONER)) {
|
||||
printHandling(req);
|
||||
req.markHandled();
|
||||
} else {
|
||||
super.handleRequest(req);
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ public class OrcSoldier extends RequestHandler {
|
||||
public void handleRequest(Request req) {
|
||||
if (req.getRequestType().equals(RequestType.COLLECT_TAX)) {
|
||||
printHandling(req);
|
||||
req.markHandled();
|
||||
} else {
|
||||
super.handleRequest(req);
|
||||
}
|
||||
|
@ -1,38 +1,78 @@
|
||||
package com.iluwatar.chain;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
*
|
||||
* Request
|
||||
*
|
||||
*/
|
||||
public class Request {
|
||||
|
||||
private String requestDescription;
|
||||
private RequestType requestType;
|
||||
/**
|
||||
* The type of this request, used by each item in the chain to see if they should or can handle
|
||||
* this particular request
|
||||
*/
|
||||
private final RequestType requestType;
|
||||
|
||||
public Request(RequestType requestType, String requestDescription) {
|
||||
this.setRequestType(requestType);
|
||||
this.setRequestDescription(requestDescription);
|
||||
/**
|
||||
* A description of the request
|
||||
*/
|
||||
private final String requestDescription;
|
||||
|
||||
/**
|
||||
* Indicates if the request is handled or not. A request can only switch state from unhandled to
|
||||
* handled, there's no way to 'unhandle' a request
|
||||
*/
|
||||
private boolean handled = false;
|
||||
|
||||
/**
|
||||
* Create a new request of the given type and accompanied description.
|
||||
*
|
||||
* @param requestType The type of request
|
||||
* @param requestDescription The description of the request
|
||||
*/
|
||||
public Request(final RequestType requestType, final String requestDescription) {
|
||||
this.requestType = Objects.requireNonNull(requestType);
|
||||
this.requestDescription = Objects.requireNonNull(requestDescription);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a description of the request
|
||||
*
|
||||
* @return A human readable description of the request
|
||||
*/
|
||||
public String getRequestDescription() {
|
||||
return requestDescription;
|
||||
}
|
||||
|
||||
public void setRequestDescription(String requestDescription) {
|
||||
this.requestDescription = requestDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of this request, used by each person in the chain of command to see if they should
|
||||
* or can handle this particular request
|
||||
*
|
||||
* @return The request type
|
||||
*/
|
||||
public RequestType getRequestType() {
|
||||
return requestType;
|
||||
}
|
||||
|
||||
public void setRequestType(RequestType requestType) {
|
||||
this.requestType = requestType;
|
||||
/**
|
||||
* Mark the request as handled
|
||||
*/
|
||||
public void markHandled() {
|
||||
this.handled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this request is handled or not
|
||||
*
|
||||
* @return <tt>true</tt> when the request is handled, <tt>false</tt> if not
|
||||
*/
|
||||
public boolean isHandled() {
|
||||
return this.handled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getRequestDescription();
|
||||
}
|
||||
|
||||
}
|
||||
|
37
chain/src/test/java/com/iluwatar/chain/OrcKingTest.java
Normal file
37
chain/src/test/java/com/iluwatar/chain/OrcKingTest.java
Normal file
@ -0,0 +1,37 @@
|
||||
package com.iluwatar.chain;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Date: 12/6/15 - 9:29 PM
|
||||
*
|
||||
* @author Jeroen Meulemeester
|
||||
*/
|
||||
public class OrcKingTest {
|
||||
|
||||
/**
|
||||
* All possible requests
|
||||
*/
|
||||
private static final Request[] REQUESTS = new Request[]{
|
||||
new Request(RequestType.DEFEND_CASTLE, "Don't let the barbarians enter my castle!!"),
|
||||
new Request(RequestType.TORTURE_PRISONER, "Don't just stand there, tickle him!"),
|
||||
new Request(RequestType.COLLECT_TAX, "Don't steal, the King hates competition ..."),
|
||||
};
|
||||
|
||||
@Test
|
||||
public void testMakeRequest() throws Exception {
|
||||
final OrcKing king = new OrcKing();
|
||||
|
||||
for (final Request request : REQUESTS) {
|
||||
king.makeRequest(request);
|
||||
assertTrue(
|
||||
"Expected all requests from King to be handled, but [" + request + "] was not!",
|
||||
request.isHandled()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -14,5 +14,9 @@
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
@ -0,0 +1,38 @@
|
||||
package com.iluwatar.decorator;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.internal.verification.VerificationModeFactory.times;
|
||||
|
||||
/**
|
||||
* Date: 12/7/15 - 7:47 PM
|
||||
*
|
||||
* @author Jeroen Meulemeester
|
||||
*/
|
||||
public class SmartTrollTest {
|
||||
|
||||
@Test
|
||||
public void testSmartTroll() throws Exception {
|
||||
// Create a normal troll first, but make sure we can spy on it later on.
|
||||
final Hostile simpleTroll = spy(new Troll());
|
||||
|
||||
// Now we want to decorate the troll to make it smarter ...
|
||||
final Hostile smartTroll = new SmartTroll(simpleTroll);
|
||||
assertEquals(30, smartTroll.getAttackPower());
|
||||
verify(simpleTroll, times(1)).getAttackPower();
|
||||
|
||||
// Check if the smart troll actions are delegated to the decorated troll
|
||||
smartTroll.attack();
|
||||
verify(simpleTroll, times(1)).attack();
|
||||
|
||||
smartTroll.fleeBattle();
|
||||
verify(simpleTroll, times(1)).fleeBattle();
|
||||
verifyNoMoreInteractions(simpleTroll);
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
package com.iluwatar.decorator;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.PrintStream;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.internal.verification.VerificationModeFactory.times;
|
||||
|
||||
/**
|
||||
* Date: 12/7/15 - 7:26 PM
|
||||
*
|
||||
* @author Jeroen Meulemeester
|
||||
*/
|
||||
public class TrollTest {
|
||||
|
||||
/**
|
||||
* The mocked standard out stream, required since the actions don't have any influence on other
|
||||
* objects, except for writing to the std-out using {@link System#out}
|
||||
*/
|
||||
private final PrintStream stdOutMock = mock(PrintStream.class);
|
||||
|
||||
/**
|
||||
* Keep the original std-out so it can be restored after the test
|
||||
*/
|
||||
private final PrintStream stdOutOrig = System.out;
|
||||
|
||||
/**
|
||||
* Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test
|
||||
*/
|
||||
@Before
|
||||
public void setUp() {
|
||||
System.setOut(this.stdOutMock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removed the mocked std-out {@link PrintStream} again from the {@link System} class
|
||||
*/
|
||||
@After
|
||||
public void tearDown() {
|
||||
System.setOut(this.stdOutOrig);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTrollActions() throws Exception {
|
||||
final Troll troll = new Troll();
|
||||
assertEquals(10, troll.getAttackPower());
|
||||
|
||||
troll.attack();
|
||||
verify(this.stdOutMock, times(1)).println(eq("The troll swings at you with a club!"));
|
||||
|
||||
troll.fleeBattle();
|
||||
verify(this.stdOutMock, times(1)).println(eq("The troll shrieks in horror and runs away!"));
|
||||
|
||||
verifyNoMoreInteractions(this.stdOutMock);
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user