在Java中运行时访问方法调用参数

时间:2011-03-16 20:39:22

标签: java unit-testing programming-languages automated-tests

我正在尝试测试一个相当可怕的方法,将其输入参数传递给另一个方法进行修改。

它非常简单,但我希望能够测试一下,在方法过程中,第一个方法的输入参数值在传递给第二个方法之前不会被修改。

现在,我知道我可以通过将传递给第二个方法的值设置为类中的公共实例变量,然后测试它是否等于传递给第一个方法的原始值。但是,我想知道是否有可能在不改变任何类的代码(完全外部)的情况下测试它。

从抽象的角度来看,在Java中是否存在反射,例如,在运行时检索方法调用的输入参数?

编辑:虽然面向方面的编程很棒,但我主要想知道这是否只能使用标准Java库。我不需要以任何特定的方式使用它 - 我只是好奇它是否可能在沼泽标准Java中。

编辑#2:该值永远不会私有设置,因此我无法使用反射来访问私有变量。我应该在最初的问题中说明。对不起。

5 个答案:

答案 0 :(得分:2)

如果您有可能将第二个类实例作为外部依赖项注入到测试对象中,则可以使用模拟框架对其进行模拟,然后捕获传递给其方法的参数。

更新

一个简单的例子,使用EasyMock(写在我的头顶,不保证它编译和工作):

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));
  }
}

答案 1 :(得分:1)

根据您要实现的目标,您可以通过Aspect Oriented Programming完成此操作。它允许您在方法调用之间“插入”代码。

看起来其他人也在想同样的事情。 :)

答案 2 :(得分:0)

出于测试目的,您可以使用反射来访问私有变量。类似的东西:

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

根据您尝试捕获的调用内容,您可能会使用Dynamic Proxies来拦截方法调用。基于Java的方法要求您定位接口,否则必须使用cglib之类的第三方库。

另一种方法是使用AoP。例如,在AspectJ项目上查看。

答案 3 :(得分:0)

你可以使用像JavaSnoop http://www.aspectsecurity.com/tools/javasnoop/这样的工具拦截调用,并使用参数做任何你想做的事情,或者验证它们。

答案 4 :(得分:0)

拦截在这里可能会有所帮助,但它的具体用法并非无足轻重,可能取决于您所使用的技术。我认为最快,最直接的方法是使用guice。