2008-12-10 11 views
4

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

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

Есть ли способ сделать эту работу?

EDIT: это может быть понятнее с примером кода, вот что моя нынешняя издевались реализация методы выглядит следующим образом:

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

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

ответ

7

Я думаю, вы можете сделать это с помощью аннотации @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

Я не проверял это, хотя ..

+0

Мне что-то не хватает. Из документа это звучит многообещающе, но, похоже, не имеет значения, использую ли я reentrent = true или false, я получаю то же поведение, что и раньше. Также в документе говорится: «По умолчанию такие вызовы не допускаются, потому что они приводят к бесконечной рекурсии ...», поэтому я смущен. – 2008-12-11 15:38:20

1

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

Например:

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

//use toTest in test 

Сохраняя это определение в тесте также ясно, для других, каких метод в настоящее время «издевались».

+0

Спасибо за предложение! К несчастью, я не могу использовать этот подход, потому что класс, который я издеваюсь, фактически не создается непосредственно тестовым случаем. Он был создан объектом, который находится под контролем. – 2008-12-10 20:25:08

5

В более поздних версиях JMockit, Invocation.proceed() можно вызывать из MockUp реализации. См. Faking: Proceeding into the real implementation.

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

 Смежные вопросы

  • Нет связанных вопросов^_^