2016-05-18 3 views
0

Попытка получить Mockito и PowerMock вести себя, но я получаю UnfinishedStubbingException при попытке запустить этот код:PowerMock UnfinishedStubbingException ошибка конечного класса

@RunWith(PowerMockRunner.class) 
@PrepareForTest(FileIOHelper.class) 
public class FileIOHelperTest { 

    @Test 
    public void testIOExceptionOnWrite() { 
     PowerMockito.mockStatic(FileIOHelper.class); 
     PowerMockito.doThrow(new IOException()).when(FileIOHelper.class); 
     PowerMockito.verifyStatic(); 
     FileIOHelper.write(Mockito.anyString(), Mockito.anyString()); 
    } 

    @After 
    public void validate() { 
     Mockito.validateMockitoUsage(); 
    } 

} 

и этот класс IO

public final class FileIOHelper { 

    public static void write(final String file, String message, final boolean appendNewLine) { 
     if(checkArgs(file, message)) { 
      final Path path = Paths.get(file); 
      StandardOpenOption mode = StandardOpenOption.APPEND; 
      if(Files.notExists(path)) { 
       mode = StandardOpenOption.CREATE_NEW; 
      } 
      if(appendNewLine) { 
       message += System.getProperty("line.separator"); 
      } 
      try { 
       Files.write(path, message.getBytes(), mode); 
      } catch(IOException e) { 
       handleException(e, "Problem writing to " + file); 
      } 
     } 
    } 

    private static boolean checkArgs(final String... args) { 
     if(args != null && args.length > 0) { 
      for(final String arg : args) { 
       if(arg == null || arg.isEmpty()) { 
        return false; 
       } 
      } 
     } 

     return true; 
    } 

    private static void handleException(final IOException e, final String errorMsg) { 
     handleException(e, errorMsg, true); 
    } 

    private static void handleException(final IOException e, final String errorMsg, final boolean printStace) { 
     checkArgs(errorMsg); 

     System.err.println(errorMsg); 
     System.err.println(e.getMessage()); 

     if(printStace) { 
      e.printStackTrace(); 
     } 
    } 

} 

То, что я хочу сделать, это как-то вызвать IOException, так что можно проверить handleException. Почему можно спросить? Я смотрю на моем докладе Jacoco и я вижу это:

jacoco report

Я посмотрел на:

и я все еще полностью потерян. Я понятия не имею, нужно ли мне запускать IOException или я могу как-то проверить вывод handleException без doThrow. Кто-то, помогите!

Журнал ошибок:

org.mockito.exceptions.misusing.UnfinishedStubbingException: 
Unfinished stubbing detected here: 
-> at FileIOHelperTest.testIOExceptionOnWrite(FileIOHelperTest.java:8) // doThrow line 

E.g. thenReturn() may be missing. 
Examples of correct stubbing: 
    when(mock.isOk()).thenReturn(true); 
    when(mock.isOk()).thenThrow(exception); 
    doThrow(exception).when(mock).someVoidMethod(); 
Hints: 
1. missing thenReturn() 
2. you are trying to stub a final method, you naughty developer! 
3: you are stubbing the behaviour of another mock inside before 'thenReturn' instruction if completed 

ответ

1

Моя рекомендация: забыть об использовании PowerMock.

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

PowerMock выглядит как решение многих проблем; но скорее, чем позже, это станет причиной и многое другое проблемы. Это нарушает охват, это затрудняет изменение базовой JVM и т. Д.

Серьезно: если ваш дизайн может быть протестирован только с помощью PowerMock, это очень часто свидетельствует о том, что ваш дизайн плохой. Итак: сосредоточьтесь на переработке вашего кода под тестированием; вместо того, чтобы вкладывать время в такой инструмент, как PowerMock, который приносит больше вреда, чем пользы.

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

В вашем случае: сначала избегайте статических повсеместно. В основном вы достигаете этого (в худшем случае), вытягивая маленькие классы-оболочки вокруг статических вызовов, которые вы должны выполнить. Для тестирования вы можете издеваться над оберточным объектом; и в производственном коде вы используете инъекцию зависимостей, чтобы предоставить объект оболочки (singleton/enum), который просто делает статический вызов.

+0

Помимо мнения, я нутро ощущения, что накладные расходы powermock и mokito перевешивают его использование. Причина, по которой я обратился к этому, в первую очередь заключается в том, что я не имел понятия, как умышленно «вызывать» «IOException». Если вы можете указать, как это сделать, я могу принять ответ. Кроме того, я вижу, почему использование 'static', но в контексте этого, я не уверен, что альтернатива. Возможно, синглтон? – djthoms

+0

Я добавил несколько предложений в последнем абзаце ... (и я не вижу хорошего способа вызвать исключение IOException). – GhostCat

0
  1. Прежде всего, исключение IOException - исключение - оно должно быть объявлено с помощью бросков в сигнатуре метода. Но ваш метод FileIOHelper.write не имеет такого. Это может быть причиной исключения UnsutisfiedStubbingException.
  2. Я не понимаю, что вы пытаетесь проверить: если FileIOHelper - это mock-handleException, никогда не будет вызываться, поскольку он вызывается реальным методом записи, а не издевается.
0

Во-первых, вам нужно высмеять класс «Файлы», а не «FileIOHelper». FileIOHelper - это проверенный класс. Во-вторых, вы не указали, какой метод должен вызывать IOException. Метод испытания прибора должен быть следующим (предполагая, испытанный метод уловы и управлять IOException):

@RunWith(PowerMockRunner.class) 
@PrepareForTest(Files.class) 
public class FileIOHelperTest { 

    @Test 
    public void testIOExceptionOnWrite() { 
    PowerMockito.mockStatic(Files.class); 
    PowerMockito.doThrow(new IOException()).when(Files.class); 
    Files.write("path", "message", true); 
    FileIOHelper.write("path", "message", true); 
    PowerMockito.verifyStatic(); 
    Files.write("path", "message", true); 
    } 
}