2010-11-22 6 views
3

У меня проблема с Mockito.Единичное тестирование с mockito (частичное издевательство)

Можно ли сделать такую ​​вещь:

ClassX x = mock(ClassX.class) 
when(x.methodB()).thenReturn("toto"); 
String result = x.methodA(); 

Я работаю с Mockito 1.7.

Я видел там была система «шпион», но они говорят, что не рекомендуется использовать его (почему?) По этому вопросу мы тестируем ...

Я попробовал эту функцию шпиона в любом случае, но я получаю странное поведение ,

Проверить, что я хочу сделать:

Реальный код:

String methodA(String arg) { 
    return this.methodB(arg); 
} 

String methodB(String arg) { 
    return "toto"; 
} 

Код испытания:

@Test 
public void testTest() { 
    final ClassX x = spy(new ClassX()); 
    final String argument = "arg"; 
    doReturn("good").when(helper).methodB(argument); 
    assertTrue( x.methodB(argument).equals("good")); 
    assertTrue( x.methodA(argument).equals("good")); 
} 

Как они сказали, что я избегал когда thenReturn синтаксис, что может быть проблема с шпион (но он все равно не работает)

Странно, что: assertTrue (x.methodB (аргумент) .equals ("good")); ОК

Только второй assertTrue (x.methodA (аргумент) .equals ("good")); не в порядке

Собственно helper.methodA (аргумент) возвращает «Тото» -> реальный результат, а не фиктивный результат

Это не возможно сказать Mockito вернуться «хорошо» в этом случае? ?? Кажется, что когда класс класса вызывает метод B, это нормально, но если метод шпиона вызывает методB, он больше не работает ...

Я не знаю, что делать ... это такое странное вещь для модульного тестирования 2 метода одного и того же класса и сделать тесты независимыми друг от друга, чтобы знаменитая фреймворк-макет не реализовал эту основную функцию? Разве это не то, что мы называем реальным модульным тестированием? Не понимаю, почему они говорят, чтобы избежать использования метода шпиона на тестируемом объекте ...

Благодаря

+0

Просто попробовал это с Mockito 1.9.5, и оба возвратили '' good ''. Поэтому я думаю, что это пошло. – acdcjunior

ответ

2

Шпион является другим объектом из осматривал объекта. Шпион только делегирует шпионский объект. Поэтому, когда объект spied вызывает метод B из метода A, он будет называть его сам по себе, а не шпионом.

+0

Спасибо :) но у вас есть решение делать то, что я хочу? –

+0

Думаю, я мог бы использовать анонимный реальный класс и переопределить MethodB, но mockito не подходит для этого решения? –

+0

Вместо этого используйте 'methodB' на другом объекте, который вы предоставляете в качестве зависимости для объекта, который имеет' methodA', например, в качестве параметра конструктора. Таким образом, вы можете издеваться над объектом 'methodB'. Если вы дадите собственные имена своих объектов и методов, я могу предложить вам лучшие имена. –

4

ОБНОВЛЕНИЕ: Я написал материал ниже, а затем через несколько мгновений обнаружил .thenCallRealMethod(), который позволяет вам эффективно выполнять частичную штриховку. Авторы Mockito рекомендуют использовать рефакторинг для разделения зависимостей на разные классы; но они обеспечивают средства для частичного закрытия. Я добавил метод тестирования, чтобы продемонстрировать этот подход, и оставляю свои оригинальные комментарии.

ОРИГИНАЛ: Мне очень нравится Мокито, но это единственное место, где побеждает EasyMock. У меня есть два решения для вас, которые не связаны с Mockito. Первый - переопределить методB в вашем экземпляре тестирования. Другой - частично издеваться над EasyMock:

import org.junit.Test; 
import static org.junit.Assert.*; 
import static org.easymock.EasyMock.*; 

public class PartialMockTest { 

    class ClassX { 
     String methodA(String arg) {return methodB(arg);} 
     String methodB(String arg) {return "toto";} 
    } 

    @Test 
    public void MockitoOnClassX(){ 
     ClassX classx = mock(ClassX.class); 
     when(classx.methodB("hiyas")).thenReturn("tomtom"); 
     when(classx.methodA(anyString())).thenCallRealMethod(); 
     String response = classx.methodA("hiyas"); 
     assertEquals("tomtom",response); 
    } 


    @Test 
    public void OverrideOnClassX() { 
     ClassX classx = new ClassX(){@Override String methodB(String arg){return "tomtom";}}; 
     String response = classx.methodA("hiyas"); 
     assertEquals("tomtom",response); 
    } 

    @Test 
    public void PartialMockOnClassX() throws NoSuchMethodException { 
     ClassX classx = createMockBuilder(ClassX.class).addMockedMethod("methodB").createMock(); 
     expect(classx.methodA("hiyas")).andReturn("tomtom"); 
     replay(classx); 
     String response = classx.methodA("hiyas"); 
     assertEquals("tomtom",response); 
    } 

}