1   package com.lexicalscope.fluentreflection.endtoend;
2   
3   import static com.lexicalscope.fluentreflection.FluentReflection.type;
4   import static com.lexicalscope.fluentreflection.ReflectionMatchers.*;
5   import static org.hamcrest.MatcherAssert.assertThat;
6   import static org.hamcrest.Matchers.*;
7   
8   import org.junit.Rule;
9   import org.junit.Test;
10  import org.junit.rules.ExpectedException;
11  
12  import com.lexicalscope.fluentreflection.IllegalArgumentRuntimeException;
13  
14  public class TestReflectedClassInstanceMethod {
15      @Rule public final ExpectedException exception = ExpectedException.none();
16  
17      public static class ClassWithInstanceMethods {
18          private boolean called;
19          private boolean objectCalled;
20          private boolean stringCalled;
21          private boolean stringAndIntegerCalled;
22  
23          public void simpleMethod() {
24              called = true;
25          }
26  
27          public int methodWithReturnValue() {
28              return 42;
29          }
30  
31          public void methodWithOneArgument(final String string) {
32              stringCalled = true;
33          }
34  
35          public void methodWithTwoArguments(final String string, final Integer integer) {
36              stringAndIntegerCalled = true;
37          }
38  
39          public void methodWithOneArgument(final Object object) {
40              objectCalled = true;
41          }
42      }
43  
44      private final ClassWithInstanceMethods instance = new ClassWithInstanceMethods();
45  
46      @Test public void simpleMethodCanBeCalled() {
47          type(ClassWithInstanceMethods.class).method(hasName("simpleMethod")).callRaw(instance);
48  
49          assertThat(instance.called, equalTo(true));
50      }
51  
52      @Test public void callingMethodWithReturnValueReturnsValue() {
53          final Integer result =
54                  (Integer) type(ClassWithInstanceMethods.class)
55                          .method(hasName("methodWithReturnValue"))
56                          .callRaw(instance);
57  
58          assertThat(result, equalTo(42));
59      }
60  
61      @Test public void canCallMethodWithOneArgumentIfMultipleMatches() {
62          type(ClassWithInstanceMethods.class).method(hasName("methodWithOneArgument")).callRaw(instance, "string");
63  
64          assertThat(instance.stringCalled || instance.objectCalled, equalTo(true));
65      }
66  
67      @Test public void methodWithTwoArgumentsCanBeCalled() {
68          type(ClassWithInstanceMethods.class).method(hasName("methodWithTwoArguments")).callRaw(
69                  instance,
70                  "string",
71                  42);
72  
73          assertThat(instance.stringAndIntegerCalled, equalTo(true));
74      }
75  
76      @Test public void methodWithTwoArgumentsHasCorrectArgumentCount() {
77          assertThat(
78                  type(ClassWithInstanceMethods.class).method(hasName("methodWithTwoArguments")).argCount(),
79                  equalTo(2));
80      }
81  
82      @SuppressWarnings("unchecked") @Test public void instanceMethodArgumentTypeIsCorrect() throws Exception {
83          assertThat(
84                  type(ClassWithInstanceMethods.class).method(hasName("methodWithTwoArguments")).args(),
85                  contains(
86                          reflectingOn(String.class),
87                          reflectingOn(Integer.class)));
88      }
89  
90      @Test public void callingInstanceMethodWithoutInstanceFails() {
91          exception.expect(IllegalArgumentException.class);
92          exception.expectMessage("target instance must be specified");
93  
94          type(ClassWithInstanceMethods.class).method(hasName("simpleMethod")).callRaw();
95      }
96  
97      @Test public void callingInstanceMethodWithWrongInstanceType() {
98          exception.expect(IllegalArgumentRuntimeException.class);
99          exception.expectMessage(containsString("not an instance of declaring class"));
100 
101         type(ClassWithInstanceMethods.class).method(hasName("simpleMethod")).callRaw(new Object());
102     }
103 }