Skip to content

Commit d7dd8d4

Browse files
committed
Merge pull request iluwatar#312 from fluxw42/master
Add proper unit tests for chain, bridge and builder pattern iluwatar#293
2 parents 4e7a8fd + 10a94cc commit d7dd8d4

File tree

14 files changed

+402
-13
lines changed

14 files changed

+402
-13
lines changed

bridge/pom.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,9 @@
1414
<artifactId>junit</artifactId>
1515
<scope>test</scope>
1616
</dependency>
17+
<dependency>
18+
<groupId>org.mockito</groupId>
19+
<artifactId>mockito-core</artifactId>
20+
</dependency>
1721
</dependencies>
1822
</project>
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.iluwatar.bridge;
2+
3+
import org.junit.Test;
4+
5+
import static org.mockito.Mockito.spy;
6+
import static org.mockito.Mockito.verify;
7+
import static org.mockito.Mockito.verifyNoMoreInteractions;
8+
import static org.mockito.internal.verification.VerificationModeFactory.times;
9+
10+
/**
11+
* Date: 12/6/15 - 11:15 PM
12+
*
13+
* @author Jeroen Meulemeester
14+
*/
15+
public class BlindingMagicWeaponTest extends MagicWeaponTest {
16+
17+
/**
18+
* Invoke all possible actions on the weapon and check if the actions are executed on the actual
19+
* underlying weapon implementation.
20+
*/
21+
@Test
22+
public void testExcalibur() throws Exception {
23+
final Excalibur excalibur = spy(new Excalibur());
24+
final BlindingMagicWeapon blindingMagicWeapon = new BlindingMagicWeapon(excalibur);
25+
26+
testBasicWeaponActions(blindingMagicWeapon, excalibur);
27+
28+
blindingMagicWeapon.blind();
29+
verify(excalibur, times(1)).blindImp();
30+
verifyNoMoreInteractions(excalibur);
31+
}
32+
33+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.iluwatar.bridge;
2+
3+
import org.junit.Test;
4+
5+
import static org.mockito.Mockito.spy;
6+
import static org.mockito.Mockito.verify;
7+
import static org.mockito.Mockito.verifyNoMoreInteractions;
8+
import static org.mockito.internal.verification.VerificationModeFactory.times;
9+
10+
/**
11+
* Date: 12/6/15 - 11:26 PM
12+
*
13+
* @author Jeroen Meulemeester
14+
*/
15+
public class FlyingMagicWeaponTest extends MagicWeaponTest {
16+
17+
/**
18+
* Invoke all possible actions on the weapon and check if the actions are executed on the actual
19+
* underlying weapon implementation.
20+
*/
21+
@Test
22+
public void testMjollnir() throws Exception {
23+
final Mjollnir mjollnir = spy(new Mjollnir());
24+
final FlyingMagicWeapon flyingMagicWeapon = new FlyingMagicWeapon(mjollnir);
25+
26+
testBasicWeaponActions(flyingMagicWeapon, mjollnir);
27+
28+
flyingMagicWeapon.fly();
29+
verify(mjollnir, times(1)).flyImp();
30+
verifyNoMoreInteractions(mjollnir);
31+
}
32+
33+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.iluwatar.bridge;
2+
3+
import static org.junit.Assert.assertNotNull;
4+
import static org.mockito.Mockito.verify;
5+
import static org.mockito.Mockito.verifyNoMoreInteractions;
6+
import static org.mockito.internal.verification.VerificationModeFactory.times;
7+
8+
/**
9+
* Date: 12/6/15 - 11:28 PM
10+
*
11+
* @author Jeroen Meulemeester
12+
*/
13+
public abstract class MagicWeaponTest {
14+
15+
/**
16+
* Invoke the basic actions of the given weapon, and test if the underlying weapon implementation
17+
* is invoked
18+
*
19+
* @param weaponImpl The spied weapon implementation where actions are bridged to
20+
* @param weapon The weapon, handled by the app
21+
*/
22+
protected final void testBasicWeaponActions(final MagicWeapon weapon,
23+
final MagicWeaponImpl weaponImpl) {
24+
assertNotNull(weapon);
25+
assertNotNull(weaponImpl);
26+
assertNotNull(weapon.getImp());
27+
28+
weapon.swing();
29+
verify(weaponImpl, times(1)).swingImp();
30+
verifyNoMoreInteractions(weaponImpl);
31+
32+
weapon.wield();
33+
verify(weaponImpl, times(1)).wieldImp();
34+
verifyNoMoreInteractions(weaponImpl);
35+
36+
weapon.unwield();
37+
verify(weaponImpl, times(1)).unwieldImp();
38+
verifyNoMoreInteractions(weaponImpl);
39+
40+
}
41+
42+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.iluwatar.bridge;
2+
3+
import org.junit.Test;
4+
5+
import static org.mockito.Mockito.spy;
6+
import static org.mockito.Mockito.verify;
7+
import static org.mockito.Mockito.verifyNoMoreInteractions;
8+
import static org.mockito.internal.verification.VerificationModeFactory.times;
9+
10+
/**
11+
* Date: 12/6/15 - 11:43 PM
12+
*
13+
* @author Jeroen Meulemeester
14+
*/
15+
public class SoulEatingMagicWeaponTest extends MagicWeaponTest {
16+
17+
/**
18+
* Invoke all possible actions on the weapon and check if the actions are executed on the actual
19+
* underlying weapon implementation.
20+
*/
21+
@Test
22+
public void testStormBringer() throws Exception {
23+
final Stormbringer stormbringer = spy(new Stormbringer());
24+
final SoulEatingMagicWeapon soulEatingMagicWeapon = new SoulEatingMagicWeapon(stormbringer);
25+
26+
testBasicWeaponActions(soulEatingMagicWeapon, stormbringer);
27+
28+
soulEatingMagicWeapon.eatSoul();
29+
verify(stormbringer, times(1)).eatSoulImp();
30+
verifyNoMoreInteractions(stormbringer);
31+
}
32+
33+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package com.iluwatar.builder;
2+
3+
import org.junit.Test;
4+
5+
import static org.junit.Assert.assertEquals;
6+
import static org.junit.Assert.assertNotNull;
7+
8+
/**
9+
* Date: 12/6/15 - 11:01 PM
10+
*
11+
* @author Jeroen Meulemeester
12+
*/
13+
public class HeroTest {
14+
15+
/**
16+
* Test if we get the expected exception when trying to create a hero without a profession
17+
*/
18+
@Test(expected = IllegalArgumentException.class)
19+
public void testMissingProfession() throws Exception {
20+
new Hero.HeroBuilder(null, "Sir without a job");
21+
}
22+
23+
/**
24+
* Test if we get the expected exception when trying to create a hero without a name
25+
*/
26+
@Test(expected = IllegalArgumentException.class)
27+
public void testMissingName() throws Exception {
28+
new Hero.HeroBuilder(Profession.THIEF, null);
29+
}
30+
31+
/**
32+
* Test if the hero build by the builder has the correct attributes, as requested
33+
*/
34+
@Test
35+
public void testBuildHero() throws Exception {
36+
final String heroName = "Sir Lancelot";
37+
38+
final Hero hero = new Hero.HeroBuilder(Profession.WARRIOR, heroName)
39+
.withArmor(Armor.CHAIN_MAIL)
40+
.withWeapon(Weapon.SWORD)
41+
.withHairType(HairType.LONG_CURLY)
42+
.withHairColor(HairColor.BLOND)
43+
.build();
44+
45+
assertNotNull(hero);
46+
assertNotNull(hero.toString());
47+
assertEquals(Profession.WARRIOR, hero.getProfession());
48+
assertEquals(heroName, hero.getName());
49+
assertEquals(Armor.CHAIN_MAIL, hero.getArmor());
50+
assertEquals(Weapon.SWORD, hero.getWeapon());
51+
assertEquals(HairType.LONG_CURLY, hero.getHairType());
52+
assertEquals(HairColor.BLOND, hero.getHairColor());
53+
54+
}
55+
56+
}

chain/src/main/java/com/iluwatar/chain/OrcCommander.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public OrcCommander(RequestHandler handler) {
1515
public void handleRequest(Request req) {
1616
if (req.getRequestType().equals(RequestType.DEFEND_CASTLE)) {
1717
printHandling(req);
18+
req.markHandled();
1819
} else {
1920
super.handleRequest(req);
2021
}

chain/src/main/java/com/iluwatar/chain/OrcOfficer.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public OrcOfficer(RequestHandler handler) {
1515
public void handleRequest(Request req) {
1616
if (req.getRequestType().equals(RequestType.TORTURE_PRISONER)) {
1717
printHandling(req);
18+
req.markHandled();
1819
} else {
1920
super.handleRequest(req);
2021
}

chain/src/main/java/com/iluwatar/chain/OrcSoldier.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public OrcSoldier(RequestHandler handler) {
1515
public void handleRequest(Request req) {
1616
if (req.getRequestType().equals(RequestType.COLLECT_TAX)) {
1717
printHandling(req);
18+
req.markHandled();
1819
} else {
1920
super.handleRequest(req);
2021
}
Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,78 @@
11
package com.iluwatar.chain;
22

3+
import java.util.Objects;
4+
35
/**
4-
*
56
* Request
6-
*
77
*/
88
public class Request {
99

10-
private String requestDescription;
11-
private RequestType requestType;
10+
/**
11+
* The type of this request, used by each item in the chain to see if they should or can handle
12+
* this particular request
13+
*/
14+
private final RequestType requestType;
15+
16+
/**
17+
* A description of the request
18+
*/
19+
private final String requestDescription;
1220

13-
public Request(RequestType requestType, String requestDescription) {
14-
this.setRequestType(requestType);
15-
this.setRequestDescription(requestDescription);
21+
/**
22+
* Indicates if the request is handled or not. A request can only switch state from unhandled to
23+
* handled, there's no way to 'unhandle' a request
24+
*/
25+
private boolean handled = false;
26+
27+
/**
28+
* Create a new request of the given type and accompanied description.
29+
*
30+
* @param requestType The type of request
31+
* @param requestDescription The description of the request
32+
*/
33+
public Request(final RequestType requestType, final String requestDescription) {
34+
this.requestType = Objects.requireNonNull(requestType);
35+
this.requestDescription = Objects.requireNonNull(requestDescription);
1636
}
1737

38+
/**
39+
* Get a description of the request
40+
*
41+
* @return A human readable description of the request
42+
*/
1843
public String getRequestDescription() {
1944
return requestDescription;
2045
}
2146

22-
public void setRequestDescription(String requestDescription) {
23-
this.requestDescription = requestDescription;
24-
}
25-
47+
/**
48+
* Get the type of this request, used by each person in the chain of command to see if they should
49+
* or can handle this particular request
50+
*
51+
* @return The request type
52+
*/
2653
public RequestType getRequestType() {
2754
return requestType;
2855
}
2956

30-
public void setRequestType(RequestType requestType) {
31-
this.requestType = requestType;
57+
/**
58+
* Mark the request as handled
59+
*/
60+
public void markHandled() {
61+
this.handled = true;
62+
}
63+
64+
/**
65+
* Indicates if this request is handled or not
66+
*
67+
* @return <tt>true</tt> when the request is handled, <tt>false</tt> if not
68+
*/
69+
public boolean isHandled() {
70+
return this.handled;
3271
}
3372

3473
@Override
3574
public String toString() {
3675
return getRequestDescription();
3776
}
77+
3878
}

0 commit comments

Comments
 (0)