Доступ к параметрам вызова метода во время выполнения в Java - PullRequest
1 голос
/ 16 марта 2011

Я пытаюсь протестировать довольно ужасный метод, который передает свой входной параметр другому для модификации метода.

Это довольно тривиально, но я хотел бы иметь возможность проверить, что в ходе метода значение входного параметра для первого метода не изменяется до его передачи во второй метод.

Теперь я знаю, что мог бы сделать это, задав значение, передаваемое второму методу, в качестве общедоступной переменной экземпляра в классе, а затем проверив, что оно равно исходному значению, переданному первому методу. Тем не менее, мне было интересно, можно ли было проверить это без изменения какого-либо кода класса (полностью внешний).

Говоря абстрактно, есть ли в Java, например, с отражением, возможность получить входной параметр для вызова метода во время выполнения?

РЕДАКТИРОВАТЬ: Хотя аспектно-ориентированное программирование было бы замечательно, я в основном интересовался, возможно ли это, используя только стандартную библиотеку Java. Мне это не нужно каким-то конкретным образом - мне просто любопытно, возможно ли это в болотной стандартной Java.

РЕДАКТИРОВАТЬ # 2: Значение также никогда не устанавливается в частном порядке, поэтому я не могу использовать отражение для доступа к закрытой переменной. Я должен был заявить об этом в первоначальном вопросе. Извините всех.

Ответы [ 5 ]

2 голосов
/ 16 марта 2011

Если у вас есть возможность внедрить экземпляр второго класса в тестируемый объект как внешнюю зависимость, вы можете смоделировать его с помощью среды моделирования, а затем захватить параметр, переданный его методу.

Обновление

Упрощенный пример с использованием 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 голос
/ 16 марта 2011

В зависимости от того, чего вы пытаетесь достичь, вы можете достичь этого с помощью Аспектно-ориентированного программирования .Это позволит вам «вставлять» код между вызовами методов.

Похоже, кто-то еще тоже думал об этом.:)

0 голосов
/ 16 марта 2011

Перехват может быть полезен здесь, но его конкретное использование не тривиально и может зависеть от технологии, которую вы используете. На мой взгляд, самый быстрый и понятный подход - использовать хитрость.

0 голосов
/ 16 марта 2011

Вы можете использовать такой инструмент, как JavaSnoop http://www.aspectsecurity.com/tools/javasnoop/, чтобы перехватить вызов и сделать с параметрами все, что вы хотите, или проверить их.

0 голосов
/ 16 марта 2011

В целях тестирования вы можете использовать отражение для доступа к закрытым переменным.Примерно так:

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

В зависимости от того, как выглядит вызов, который вы пытаетесь перехватить, вы можете использовать Динамические прокси для перехвата вызовов методов.Подход, основанный только на Java, требует, чтобы вы указали интерфейс, в противном случае должна использоваться сторонняя библиотека, такая как cglib .

Другим другим подходом будет использование AoP.Посмотрите, например, на проект AspectJ.

...