commit 44: adc0b4871fe8
parent 43: b4029fbec56f
branch: default
tags: tip
[am, ap, pairwithus] New Behaviour: Clerk can fill in details on any object, Clerk will complain when method does not exist, and when the Object being filled in complains. S02E10 S02E11
AntonyMarcano
8 months ago

Changed (Δ7.1 KB):

raw changeset »

src/org/jnarrate/fit/fixture/NarrativeFixture.java (2 lines added, 2 lines removed)

src/org/jnarrate/fit/fixture/entityname/Information.java

src/org/jnarrate/fit/fixture/expertise/Clerk.java (87 lines added, 0 lines removed)

src/org/jnarrate/fit/fixture/expertise/SubjectMatterExpert.java (2 lines added, 3 lines removed)

src/org/jnarrate/fit/fixture/expertise/misuse/InvokedCodeComplainedComplaint.java (12 lines added, 0 lines removed)

src/org/jnarrate/fit/fixture/expertise/misuse/UnableToFillInDetailsComplaint.java (11 lines added, 0 lines removed)

test/org/jnarrate/fit/fixture/NarrativeFixtureTest.java (2 lines added, 2 lines removed)

test/org/jnarrate/fit/fixture/entityname/ClerkShould.java (89 lines added, 0 lines removed)

test/org/jnarrate/fit/fixture/entityname/InformationShould.java

test/org/jnarrate/fit/fixture/entityname/information/ActionWithAMethodName.java

test/org/jnarrate/fit/fixture/entityname/information/ObjectWithAMethodName.java (9 lines added, 0 lines removed)

test/org/jnarrate/fit/fixture/expertise/SubjectMatterExpertTest.java (3 lines added, 4 lines removed)

Up to file-list src/org/jnarrate/fit/fixture/NarrativeFixture.java:

@@ -8,10 +8,10 @@ import org.jnarrate.action.PerformableAs
8
8
import org.jnarrate.fit.fixture.entityname.ActionName;
9
9
import org.jnarrate.fit.fixture.entityname.CharacterName;
10
10
import org.jnarrate.fit.fixture.entityname.Demographic;
11
import org.jnarrate.fit.fixture.entityname.Information;
12
11
import org.jnarrate.fit.fixture.entityname.QuestionName;
13
12
import org.jnarrate.fit.fixture.entityname.RoleName;
14
13
import org.jnarrate.fit.fixture.expertise.CastingDirector;
14
import org.jnarrate.fit.fixture.expertise.Clerk;
15
15
import org.jnarrate.fit.fixture.expertise.SubjectMatterExpert;
16
16
import org.jnarrate.question.AnswerableBy;
17
17
import org.jnarrate.sugar.Given;
@@ -60,7 +60,7 @@ public class NarrativeFixture extends Do
60
60
	
61
61
	public <ROLE> void whenAttemptsToWith(String theCharacter, String doThis, String thisInformation) {
62
62
	  ActorPlayingThe<ROLE> actor = castingDirector.whoIsPlaying(new CharacterName(theCharacter));
63
    PerformableAsA<ROLE> doThisAction = sme.howDoI(new ActionName(doThis), new Information(thisInformation));
63
    PerformableAsA<ROLE> doThisAction = sme.howDoI(new ActionName(doThis), new Clerk(thisInformation));
64
64
    
65
65
    When.the(actor).attemptsTo(doThisAction);
66
66
	}

Up to file-list src/org/jnarrate/fit/fixture/expertise/Clerk.java:

1
package org.jnarrate.fit.fixture.expertise;
2
3
import java.lang.reflect.InvocationTargetException;
4
import java.lang.reflect.Method;
5
import java.util.regex.Matcher;
6
import java.util.regex.Pattern;
7
8
import org.jnarrate.fit.fixture.entityname.MethodName;
9
import org.jnarrate.fit.fixture.expertise.misuse.InvokedCodeComplainedComplaint;
10
import org.jnarrate.fit.fixture.expertise.misuse.UnableToFillInDetailsComplaint;
11
12
public class Clerk {
13
14
  private static final String BEFORE_THE_FIRST_QUOTE = "^(.*) \"";
15
  private static final String INSIDE_QUOTES = "\"(.*)\"";
16
  private final String value;
17
  private final MethodName methodName;
18
19
  public Clerk(String fromThisSentenceFragment) {
20
    methodName = new MethodName(theText(BEFORE_THE_FIRST_QUOTE,fromThisSentenceFragment));
21
    value = theText(INSIDE_QUOTES, fromThisSentenceFragment);
22
  }
23
  private String theText(String thisPattern, String fromThisSentenceFragment) {
24
    Pattern valuePattern = Pattern.compile(thisPattern);
25
    Matcher matcher = valuePattern.matcher(fromThisSentenceFragment);
26
    matcher.find();
27
    return matcher.group(1);
28
  }
29
30
  public <T> T addTheDetailsTo(T lookedUpAction) {
31
    try {
32
      Method method = lookedUpAction.getClass().getMethod(methodName.toString(), String.class);
33
      method.invoke(lookedUpAction, value);
34
      return lookedUpAction;
35
    }
36
    catch (NoSuchMethodException e) {
37
      throw new UnableToFillInDetailsComplaint(lookedUpAction, methodName, e);
38
    }
39
    catch (InvocationTargetException e) {
40
      throw new InvokedCodeComplainedComplaint(lookedUpAction, methodName, e);
41
    }
42
    catch (SecurityException e) {
43
      throw new RuntimeException("TODO - Handle this exception better",e);
44
    }
45
    catch (IllegalArgumentException e) {
46
      throw new RuntimeException("TODO - Handle this exception better",e);
47
    }
48
    catch (IllegalAccessException e) {
49
      throw new RuntimeException("TODO - Handle this exception better",e);
50
    }
51
  }
52
53
  @Override
54
  public int hashCode() {
55
    final int prime = 31;
56
    int result = 1;
57
    result = prime * result + ((methodName == null) ? 0 : methodName.hashCode());
58
    result = prime * result + ((value == null) ? 0 : value.hashCode());
59
    return result;
60
  }
61
62
  @Override
63
  public boolean equals(Object obj) {
64
    if (this == obj)
65
      return true;
66
    if (obj == null)
67
      return false;
68
    if (getClass() != obj.getClass())
69
      return false;
70
    Clerk other = (Clerk) obj;
71
    if (methodName == null) {
72
      if (other.methodName != null)
73
        return false;
74
    }
75
    else if (!methodName.equals(other.methodName))
76
      return false;
77
    if (value == null) {
78
      if (other.value != null)
79
        return false;
80
    }
81
    else if (!value.equals(other.value))
82
      return false;
83
    return true;
84
  }
85
  
86
  
87
}

Up to file-list src/org/jnarrate/fit/fixture/expertise/SubjectMatterExpert.java:

@@ -5,7 +5,6 @@ import org.jnarrate.expertise.Librarian;
5
5
import org.jnarrate.expertise.library.index.ClassName;
6
6
import org.jnarrate.expertise.library.index.PackageName;
7
7
import org.jnarrate.fit.fixture.entityname.ActionName;
8
import org.jnarrate.fit.fixture.entityname.Information;
9
8
import org.jnarrate.fit.fixture.entityname.QuestionName;
10
9
import org.jnarrate.fit.fixture.expertise.misuse.NotAnActionComplaint;
11
10
import org.jnarrate.question.AnswerableBy;
@@ -34,9 +33,9 @@ public class SubjectMatterExpert {
34
33
    }
35
34
  }
36
35
37
  public <ROLE> PerformableAsA<ROLE> howDoI(ActionName actionName, Information information) {
36
  public <ROLE> PerformableAsA<ROLE> howDoI(ActionName actionName, Clerk information) {
38
37
    PerformableAsA<ROLE> action = howDoI(actionName);
39
    return information.addYourselfToThe(action);
38
    return information.addTheDetailsTo(action);
40
39
  }
41
40
42
41
  public <ROLE, T> AnswerableBy<ROLE, T> howDoIAnswer(QuestionName questionName) {

Up to file-list src/org/jnarrate/fit/fixture/expertise/misuse/InvokedCodeComplainedComplaint.java:

1
package org.jnarrate.fit.fixture.expertise.misuse;
2
3
import java.lang.reflect.InvocationTargetException;
4
import org.jnarrate.fit.fixture.entityname.MethodName;
5
6
public class InvokedCodeComplainedComplaint extends RuntimeException {
7
8
  public InvokedCodeComplainedComplaint(Object invokedAction, MethodName methodName, InvocationTargetException wrappedException) {
9
    super("The method ["+ methodName +"] on the class ["+ invokedAction.getClass().getCanonicalName() +"] complained with ["+ wrappedException.getCause().getClass().getSimpleName() +"]", wrappedException.getCause() );
10
  }
11
12
}

Up to file-list src/org/jnarrate/fit/fixture/expertise/misuse/UnableToFillInDetailsComplaint.java:

1
package org.jnarrate.fit.fixture.expertise.misuse;
2
3
import org.jnarrate.fit.fixture.entityname.MethodName;
4
5
public class UnableToFillInDetailsComplaint extends RuntimeException {
6
7
  public UnableToFillInDetailsComplaint(Object invokedAction, MethodName methodName, Exception wrappedException) {
8
    super("Unable to find a method called [" + methodName + "] with a String parameter on the class [" + invokedAction.getClass().getCanonicalName() + "]. Maybe you should create it", wrappedException);
9
  }
10
11
}

Up to file-list test/org/jnarrate/fit/fixture/NarrativeFixtureTest.java:

@@ -16,10 +16,10 @@ import org.jnarrate.action.PerformableAs
16
16
import org.jnarrate.fit.fixture.entityname.ActionName;
17
17
import org.jnarrate.fit.fixture.entityname.CharacterName;
18
18
import org.jnarrate.fit.fixture.entityname.Demographic;
19
import org.jnarrate.fit.fixture.entityname.Information;
20
19
import org.jnarrate.fit.fixture.entityname.QuestionName;
21
20
import org.jnarrate.fit.fixture.entityname.RoleName;
22
21
import org.jnarrate.fit.fixture.expertise.CastingDirector;
22
import org.jnarrate.fit.fixture.expertise.Clerk;
23
23
import org.jnarrate.fit.fixture.expertise.SubjectMatterExpert;
24
24
import org.jnarrate.question.AnswerableBy;
25
25
import org.jnarrate.question.Question;
@@ -154,7 +154,7 @@ public class NarrativeFixtureTest {
154
154
    andThatItIsAsked(castingDirector.whoIsPlaying(new CharacterName(theRole))).thenReturn((ActorPlayingThe) actor);
155
155
156
156
    givenThatWeHaveASubjectMatterExpertPlayedByThis(mock(SubjectMatterExpert.class));
157
    andThatItIsAsked(sme.howDoI(new ActionName(doThis), new Information(thisInformation))).thenReturn((PerformableAsA) action);
157
    andThatItIsAsked(sme.howDoI(new ActionName(doThis), new Clerk(thisInformation))).thenReturn((PerformableAsA) action);
158
158
159
159
    NarrativeFixture narrativeFixture = new NarrativeFixture(castingDirector, sme);
160
160
    narrativeFixture.whenAttemptsToWith(theRole, doThis, thisInformation);

Up to file-list test/org/jnarrate/fit/fixture/entityname/ClerkShould.java:

1
package org.jnarrate.fit.fixture.entityname;
2
3
import static org.hamcrest.CoreMatchers.instanceOf;
4
import static org.hamcrest.CoreMatchers.is;
5
import static org.junit.Assert.assertThat;
6
import static org.mockito.Mockito.doThrow;
7
import static org.mockito.Mockito.mock;
8
import static org.mockito.Mockito.verify;
9
10
import org.jnarrate.fit.fixture.entityname.information.ObjectWithAMethodName;
11
import org.jnarrate.fit.fixture.expertise.Clerk;
12
import org.jnarrate.fit.fixture.expertise.misuse.InvokedCodeComplainedComplaint;
13
import org.jnarrate.fit.fixture.expertise.misuse.UnableToFillInDetailsComplaint;
14
import org.junit.Test;
15
16
public class ClerkShould {
17
 
18
  @Test
19
  public void informTheThing() throws Exception {
20
    String withTheseDetails = "aMethodName \"a value\"";
21
22
    ObjectWithAMethodName theThing = mock(ObjectWithAMethodName.class);
23
    Clerk clerk = new Clerk(withTheseDetails);
24
25
    ObjectWithAMethodName informedThing = clerk.addTheDetailsTo(theThing);
26
27
    verify(theThing).aMethodName("a value");
28
    assertThat(informedThing, is(instanceOf(ObjectWithAMethodName.class)));
29
  }
30
31
  @Test
32
  public void informTheThingWithADifferentValue() throws Exception {
33
    String withTheseDetails = "aMethodName \"a different value\"";
34
35
    ObjectWithAMethodName theThing = mock(ObjectWithAMethodName.class);
36
    Clerk clerk = new Clerk(withTheseDetails);
37
38
    ObjectWithAMethodName informedThing = clerk.addTheDetailsTo(theThing);
39
40
    verify(theThing).aMethodName("a different value");
41
    assertThat(informedThing, is(instanceOf(ObjectWithAMethodName.class)));
42
  }
43
  
44
  @Test
45
  public void informTheThingWithADifferentMethod() throws Exception {
46
    String withTheseDetails = "a Different Method Name \"a value\"";
47
48
    ObjectWithAMethodName theThing = mock(ObjectWithAMethodName.class);
49
    Clerk clerk = new Clerk(withTheseDetails);
50
51
    ObjectWithAMethodName informedThing = clerk.addTheDetailsTo(theThing);
52
53
    verify(theThing).aDifferentMethodName("a value");
54
    assertThat(informedThing, is(instanceOf(ObjectWithAMethodName.class)));
55
  }
56
  
57
  @Test
58
  public void complainWhenNoAppropriateMethod() throws Exception {
59
    Clerk clerk = new Clerk("a method that is \"not there\"");
60
    ObjectWithAMethodName thing = mock(ObjectWithAMethodName.class);
61
    
62
    Exception thrown = null;
63
    try {
64
      clerk.addTheDetailsTo(thing);
65
    }
66
    catch (Exception caught) {
67
      thrown = caught;
68
    }
69
70
    assertThat(thrown, is(instanceOf(UnableToFillInDetailsComplaint.class)));
71
  }
72
  
73
  @Test
74
  public void complainWhenCalledMethodComplains() throws Exception {
75
    Clerk clerk = new Clerk("a method name \"but it complains\"");
76
    ObjectWithAMethodName thing = mock(ObjectWithAMethodName.class);
77
    doThrow(new UnsupportedOperationException("Whoops!")).when(thing).aMethodName("but it complains");
78
    
79
    Exception thrown = null;
80
    try {
81
      clerk.addTheDetailsTo(thing);
82
    }
83
    catch (Exception caught) {
84
      thrown = caught;
85
    }
86
87
    assertThat(thrown, is(instanceOf(InvokedCodeComplainedComplaint.class)));
88
  }
89
}

Up to file-list test/org/jnarrate/fit/fixture/entityname/information/ObjectWithAMethodName.java:

1
package org.jnarrate.fit.fixture.entityname.information;
2
3
4
public interface ObjectWithAMethodName {
5
6
  void aMethodName(String aValue);
7
  void aDifferentMethodName(String string);
8
  void aMethodWithNoParameter();
9
}

Up to file-list test/org/jnarrate/fit/fixture/expertise/SubjectMatterExpertTest.java:

@@ -15,7 +15,6 @@ import org.jnarrate.action.PerformableAs
15
15
import org.jnarrate.expertise.Librarian;
16
16
import org.jnarrate.expertise.library.index.PackageName;
17
17
import org.jnarrate.fit.fixture.entityname.ActionName;
18
import org.jnarrate.fit.fixture.entityname.Information;
19
18
import org.jnarrate.fit.fixture.entityname.QuestionName;
20
19
import org.jnarrate.fit.fixture.expertise.misuse.NotAnActionComplaint;
21
20
import org.jnarrate.question.AnswerableBy;
@@ -45,13 +44,13 @@ public class SubjectMatterExpertTest {
45
44
	  when(librarian.findMeA(new ActionName("Dummy Action"), new PackageName("org.jnarrate.action"))).thenReturn(lookedUpAction);
46
45
	  
47
46
	  SubjectMatterExpert sme = new SubjectMatterExpert(librarian);
48
	  Information information = mock(Information.class);
47
	  Clerk information = mock(Clerk.class);
49
48
	  PerformableAsA<ROLE> informedAction = mock(PerformableAsA.class);
50
    when(information.addYourselfToThe(lookedUpAction)).thenReturn(informedAction);
49
    when(information.addTheDetailsTo(lookedUpAction)).thenReturn(informedAction);
51
50
	  
52
51
	  PerformableAsA<ROLE> result = sme.howDoI(new ActionName("Dummy Action"), information);
53
52
	  
54
	  verify(information).addYourselfToThe(lookedUpAction);
53
	  verify(information).addTheDetailsTo(lookedUpAction);
55
54
	  assertThat(result, is(sameInstance(informedAction)));
56
55
  }
57
56