Как издеваться над нативными методами с помощью jMockit

Я пытаюсь использовать jMockit, чтобы заглушить вызов netscape.javascript.JSObject, который, к сожалению, является абстрактным классом с несколькими собственными методами, оба из которых плохо работают с jMockit. Есть ли способ заглушить это либо с помощью jMockit, либо с помощью простой java (я бы предпочел не вводить новую библиотеку, если это возможно)? Код, который я пытаюсь внедрить, выглядит примерно так (не спрашивайте):

JSObject win = JSObject.getWindow(this);
String someVal = (String) win.call("foo", new String[] {""});

К сожалению, я не могу изменить рассматриваемый код (еще раз, не спрашивайте), поэтому единственный способ, которым я могу провести какое-либо модульное тестирование, - это выяснить, как заглушить или иным образом исключить вызовы JSОбъект. Моя текущая фиктивная реализация возвращает новый экземпляр самого себя для вызова getWindow и возвращает постоянную строку для вызова call, но, конечно, во время выполнения она не работает, жалуясь на

ошибка переопределения класса: попытка изменить модификаторы метода

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

Изменить: из-за целевой платформы мне нужно использовать JDK 1.5 для сборки/тестирования, поэтому любое решение должно быть жизнеспособным на 1.5.


person Orclev    schedule 01.12.2009    source источник


Ответы (2)


Какую версию JMockit вы используете? Согласно этому, вы сможете без проблем издеваться над нативными методами.

@Test
public void mockNativeMethod() {
    new MockUp<Runtime>() {
        @Mock
        @SuppressWarnings("unused")
        int availableProcessors() {
            return 999;
        }
    };
    assertEquals(999, Runtime.getRuntime().availableProcessors());
}

РЕДАКТИРОВАТЬ: Как вы заметили, это не работает с Java 1.5. Я боюсь, что единственное решение состоит в том, чтобы обернуть ваши нативные объекты декоратором, который просто работает как сквозной. Это немного головная боль, но это позволит издеваться/перехватывать и т.д.

person Brian Agnew    schedule 01.12.2009
comment
Я использую последнюю версию, но проблема в том, что я вынужден использовать JDK 1.5, который не предоставляет интерфейс, позволяющий инструментировать собственные методы, необходимые для их имитации. - person Orclev; 01.12.2009

Как указал Брайан, JMockit поддерживает имитацию нативных методов. (API Expectations, показанный в приведенном ниже тесте, также поддерживает его.)

@Test // this only works under JDK 1.6+; JDK 1.5 does not support redefining natives
public void mockNativeMethod()
{
   new Expectations()
   {
      final System system = null;

      {
         System.nanoTime(); returns(0L);
      }
   };

   assertEquals(0, System.nanoTime());
}

Проблема, однако, в том, что реализация JVMTI в JDK 1.5 не очень зрелая, не поддерживает переопределение native методов.

Я понимаю, что вам нужно развернуть производственный код в среде JDK 1.5, но это не должно быть препятствием для использования JDK 1.6 в вашей среде разработки. Обычно должно быть совершенно безопасно и легко запускать тесты на JDK 1.6 и даже компилировать весь исходный код с помощью компилятора JDK 1.6. Вам просто нужно указать «цель» javac как «1.5». В Eclipse есть конфигурация «Соответствие JDK» в разделе «Свойства проекта -> Компилятор Java».

person Rogério    schedule 05.12.2009