Есть ли способ в JMockit для вызова исходного метода из смоделированного метода? - PullRequest
5 голосов
/ 10 декабря 2008

В моем фиктивном классе я использую метод foo (). Для некоторых тестовых случаев я хочу, чтобы фиктивная реализация foo () возвращала специальное значение. Для других тестовых случаев я хочу использовать реальную реализацию foo (). У меня есть логическое значение, определенное в моём классе, чтобы я мог определить в методе макета, хочу ли я вернуть специальное значение или использовать «настоящий» метод. Проблема в том, что я не могу понять, как вызвать реальный метод из смоделированного метода.

Я обнаружил, что вы можете определить специальный элемент в фиктивном объекте с именем "it" (с типом объекта, который будет насмехаться). Это позволяет вам ссылаться на реальный класс из фиктивной реализации. Итак, мой план состоял в том, чтобы, если бы мне нужно было вызвать «реальную» реализацию foo (), метод mock вызвал бы его ..foo (). Однако, это не работает, потому что вызов it.foo () просто снова вызывает фиктивную версию, а не реальную версию, поэтому я получаю бесконечную рекурсию.

Есть ли способ заставить это работать?

РЕДАКТИРОВАТЬ: это может быть яснее с примером кода, вот как выглядит моя текущая реализация смоделированного метода:

private RealClass it;
...
public SomeClass foo() {
    if(fakeIt) {
        return new SomeClass("fakevalue");
    } else {
        // doesn't work, just keeps calling the mock foo
        // in infinite recursion
        return it.foo();
    }
}

РЕДАКТИРОВАТЬ 2: Кроме того, для большинства моих тестовых случаев я НЕ хочу макетную реализацию. Поэтому моя первоначальная попытка была в том, чтобы вызывать Mockit.redefineMethods () только в тех тестовых случаях, где мне был нужен фиктивный объект. Но это не сработало - кажется, вы можете сделать это только в рамках установки / разрыва ... моя пробная реализация никогда не вызывалась, когда я пытался это сделать.

ЗАМЕЧАНИЯ ПО РЕШЕНИЮ:

Сначала я не думал, что данный ответ сработал, но, поиграв с ним еще немного, кажется, проблема в том, что я смешивал «основные» методы JMockit с методами, «управляемыми аннотациями». Очевидно, что при использовании аннотации вам нужно использовать Mockit.setupMocks, а не Mockit.redefineMethods (). Вот что наконец сработало:

@Before 
public void setUp() throws Exception
{
    Mockit.setUpMocks(MyMockClass.class);
}

Тогда для ложного класса:

@MockClass(realClass = RealClass.class)
public static class MyMockClass {
    private static boolean fakeIt = false;
    private RealClass it;

    @Mock(reentrant = true)
    public SomeClass foo() {
        if(fakeIt) {
            return new SomeClass("fakevalue");
        } else {
            return it.foo();
        }
    }
}

Ответы [ 3 ]

7 голосов
/ 11 декабря 2008

Я думаю, что вы можете сделать это с аннотацией @Mock. Из документов @Mock(reentrant=true) в вашем фиктивном классе должно это сделать.

См. http://jmockit.googlecode.com/svn/trunk/www/javadoc/mockit/Mock.html
Для примера смотрите здесь http://jmockit.googlecode.com/svn/trunk/www/tutorial/StateBasedTesting.html#reentrant

Хотя я не проверял это ..

7 голосов
/ 10 июня 2015

В более поздних версиях JMockit, Invocation.proceed() можно вызывать из реализации MockUp. См. Подделка: переход к реальной реализации .

public class MyMockClass extends MockUp<RealClass> {

    private static boolean fakeIt = false;

    @Mock
    public SomeClass foo(Invocation inv) {
        if (fakeIt) {
            return new SomeClass("fakevalue");
        } else {
            return inv.proceed();
        }
    }
}
1 голос
/ 10 декабря 2008

Вместо добавления фиктивного объекта вы также можете создать подкласс для объекта, который вы хотите протестировать, и переопределить методы, которые должны возвращать специальные значения.

Например:

RealClass toTest = new RealClass(){
      public String foo(){
          return "special value";
      }
}

//use toTest in test

Придерживаясь этого определения в своем тесте, другим также становится ясно, какие методы «высмеиваются».

...