开发者

Accessing method call parameters at runtime in Java

I am trying to test a rather horrible method t开发者_运维知识库hat passes its input parameter to another for method modification.

Its rather trivial but I'd like to be able to test that, during the course of the method, the value of the input parameter to the first method isn't modified before it is passed to the second method.

Now, I know I could do this by setting the value passed to the second method as a public instance variable in the class then testing that this was equal to the original value passed to the first method. However, I was wondering if it was possible to test this without altering any of the class's code (completely external).

In abstract terms, is there anyway in Java, with reflection for example, to retrieve an input parameter on a method call at runtime?

EDIT: Although aspect oriented programming would be great I was mainly wondering if this was possible using only the standard Java library. I don't need to this in any particular way - I'm just curious if its possible in bog standard Java.

EDIT#2: The value is never set privately either so I can't use reflection to access a private variable. I should have stated that in the original question. Sorry all.


If you have a possibility to inject the second class instance into the object under test as an external dependency, you could mock it using a mocking framework, then capture the parameter passed to its method.

Update

A simplistic example, using EasyMock (written out of the top of my head, no guarantee that it compiles and works):

class TestedClass {
  OtherClass other;
  public TestedClass() { ... }
  public void setOther(OtherClass other) {
    this.other = other;
  }
  public void someMethod(ParamClass param) {
    ...
    other.otherMethod(param);
    ...
  }
}

...

class TestClass {
  @Test
  public void test() {
    TestedClass tested = new TestedClass();
    ParamClass testParam = ...
    OtherClass other = createMock(OtherClass.class);
    Capture<ParamClass> capture = new Capture<ParamClass>();
    other.otherMethod(capture);
    replay(other);
    tested.setOther(other);
    
    tested.someMethod(testParam);

    verify(other);
    assertThat(capture.getValue(), is(testParam));
  }
}


Depending on what you are trying to achieve, you might be able to accomplish this via Aspect Oriented Programming. It will allow you to "insert" code between method calls.

Looks like someone else also was thinking the same thing. :)


You could use a tool like JavaSnoop http://www.aspectsecurity.com/tools/javasnoop/ to intercept the call and do whatever you want with the parameters and or verify them.


Interception might be of help here, but it's concrete usage is not trivial and might depent on the technology you are using. The quickest, straight forward approach in my opinion is using guice.


For testing purposes you can use reflection to access private variables. Something like:

Object instance = ...
Field f = instance.getClass().getDeclaredField("theVariable");
f.setAccessible(true);
Object value = f.get(instance);

Depending on what the invocation you're trying to capture looks like you might use Dynamic Proxies to intercept method calls. The java-only based approach requires that you target an interface, otherwise a third party library like cglib must be used.

Another other approach would be to use AoP. Have a look e.g., at the AspectJ project.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜