2014-01-21 3 views
1

Предположим, что у меня есть класс;Шпион параметр метода во время тестирования с Mockito?

public class FooBar { 

    public int getMethod(List<String> code){ 

     if(code.size() > 100) 
      throw new Exception; 

      return 0; 
    } 
} 

, и у меня есть класс испытаний следующим образом;

@RunWith(PowerMockRunner.class) 
@PrepareForTest(FooBar.class) 
public class FooBarTest{ 

    FooBar fooBarInstance; 

    @Before 
    public void setUp() { 

     //MockitoAnnotations.initMocks(this); 
     fooBarInstance = new FooBar(); 
    } 

    @Test(expected = Exception.class) 
    public void testGetCorrelationListCodesParameter() { 

     List<String> codes = Mockito.spy(new ArrayList<String>()); 
     Mockito.doReturn(150).when(codes).size(); 
     fooBarInstance.getMethod(codes); 
    } 
} 

Как я могу сделать этот метод тестирования броском исключения? Я занимаюсь часами, чтобы сделать это. Хорошо, спасибо.

+0

Какой именно звонок должен вызывать исключение? –

+0

code.size() должен возвращать более 100? – quartaela

+0

Вы пробовали это без Powermock? Или 'when (codes.size()). ThenReturn (150)'. И почему вы не используете простой макет списка вместо шпиона? –

ответ

4

Шпионаж не нужен, насмехается. Как сказал @David, также насмешка не нужна и не рекомендуется для объекта value.

Использование @Test(expected = Exception.class) имеет много недостатков, испытание может пройти, когда исключение выбрасывается из ожидаемых мест. Тест не работает, но отображается как зеленый.

Я предпочитаю тестирование стиля BDD с помощью catch-exception.

Reasons for using catch-exceptions

(...) по сравнению с использованием попытка/улове блоков.

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

(...) по сравнению с тестовыми механизмами, зависящими от бегуна, которые ловят и проверяют исключения.

  • Один тест может проверять более чем одно исключение.
  • Тест может проверить свойства брошенного исключения после исключения.
  • В тесте можно указать, каким методом следует вызывать исключение.
  • Тест не зависит от конкретного тестового бегуна (JUnit4, TestNG).
import static com.googlecode.catchexception.CatchException.caughtException; 
import static com.googlecode.catchexception.apis.CatchExceptionAssertJ.*; 

public class FooBarTest { 

    FooBar sut = new FooBar(); // System Under Test 

    @Test 
    public void shouldThrowExceptionWhenListHasTooManyElements() { 

     when(sut).getMethod(listWithSize(150)); 

     then(caughtException()).isInstanceOf(Exception.class); 
    } 

    private List<String> listWithSize(int size) { 
     return new ArrayList<String>(Arrays.asList(new String[size])); 
    } 
} 

Полный рабочий код для этого теста: https://gist.github.com/mariuszs/8543918


Не рекомендуется раствор с expected и насмешками.

@RunWith(MockitoJUnitRunner.class) 
public class FooBarTest { 

    @Mock 
    List<String> codes; 

    FooBar fooBarInstance = new FooBar(); 

    @Test(expected = Exception.class) 
    public void shouldThrowExceptionWhenListHasTooManyElements() throws Exception { 

     when(codes.size()).thenReturn(150); 

     fooBarInstance.getMethod(codes); 

    } 
} 
+0

привет MariuszS есть ли какие-то важные различия между использованием «PowerMockRunner» и «MockitoJUnitRunner» ?. и большое спасибо за ваш ответ. – quartaela

+1

PowerMock предназначен для тестирования финалов и статического устаревшего кода, в то время как Mockito предназначен для тестирования хорошо продуманного кода. – MariuszS

+0

Обратите внимание, что OP написал - 'doReturn (150) .when (коды) .size();' тоже хорошо. Он имеет тот же эффект, что и «когда (code.size()). ThenReturn (150);' или 'given (codes.size()). WillReturn (150);', и, на мой взгляд, предпочтительнее, потому что это означает что вам не нужно изучать другой синтаксис для стирания недействительных методов. –

2

Список - объект значения. Это не то, над чем мы должны насмехаться. Вы можете написать весь этот тест, не издеваясь над чем-нибудь, если вы готовы составить список, размер которого превышает 100.

Кроме того, я предпочитаю использовать механизм JNnit ExpectedException, так как он позволяет вам проверить, какая строка метод проверки исключал исключение. Это лучше, чем передача аргумента в аннотацию @Test, которая позволяет вам проверить, что исключение было выбрано где-то внутри метода.

public class FooBarTest { 
    @Rule 
    public ExpectedException exceptionRule = ExpectedException.none(); 
    private FooBar toTest = new FooBar(); 

    @Test 
    public void getMethodThrowsException_whenListHasTooManyElements() { 
     List<String> listWith101Elements = 
      new ArrayList<String>(Arrays.asList(new String[101])); 

     exceptionRule.expect(Exception.class); 
     toTest.getMethod(listWith101Elements); 
    } 
} 
+0

Вы правы, но без макета вам нужно использовать хорошее имя для списка, например 'listWith101Elements', причем макет кода читается без какого-либо специального именования. Также ваш 'listWith101Elements' имеет фиксированный размер, если в' getMethod' мы добавляем или удаляем что-то из списка, тогда весь тест будет неудачным - это плохой побочный эффект. – MariuszS

+0

Ну, я думаю, если я инициирую список из 101 объекта и передам его, я не буду сталкиваться с какими-либо проблемами, и тест завершится успешно. Тем не менее, следует ли использовать Mocking и Spying, когда это возможно, или если прохождение и тестирование поведения методов с реальными инициализированными объектами проще, тогда следует использовать второй способ? Я имею в виду, есть ли стандарт? – quartaela

+0

Представьте ситуацию, когда кто-то через некоторое время добавит 'getMethod' этот код:' code.add ("Foo"); '. Это было необходимо для некоторых новых функций. После этого тестируйте и тестируйте только Exception 'java.lang.UnsupportedOperationException', тест пройдет, потому что мы ожидаем' Exception', но больше не тестируем 'size()'. Это происходит потому, что вы проверяете * список фиксированных размеров, поддерживаемый указанным массивом *, это не обычный список. – MariuszS

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