2016-05-02 2 views
3

Во время отладки я наткнулся на что-то невероятно странное, используя Mockito 1.10. Я надеялся, что кто-то сможет объяснить поведение, воспринимаемое здесь:Почему Mockito ведет себя странно с InputStreams?

Когда я запускаю следующее, моя нить зависает, и мой тест никогда не возвращается. Процессор Java-процесса, созданный, также становится астрономическим!

@Test(expected = IOException.class) 
public void mockitoWeirdness() throws IOException { 
    final InputStream mis = mock(InputStream.class); 
    doThrow(IOException.class).when(mis).read(); 
    ByteStreams.copy(mis, new ByteArrayOutputStream()); 
} 

Когда я вручную окурок этот метод следующим образом, ожидаемый IOException брошен:

@Test(expected = IOException.class) 
public void nonMockitoExpected() throws IOException { 
    final InputStream mis = new InputStream() { 

     @Override 
     public int read() throws IOException { 
      throw new IOException(); 
     } 
    }; 
    ByteStreams.copy(mis, new ByteArrayOutputStream()); 
} 

Любая помощь в понимании, как и почему метод Mockito не удается бы фантастическим.

+0

Я не знаю реализации 'ByteStreams.copy', но, возможно, он не вызывает' read() ', который читает один байт, а скорее вызывает' read (byte []) ' –

+0

Я подозреваю, что' ByteStreams.copy() ' вызывает что-то еще в InputStream перед read(). Было бы очень полезно, если бы у нас был код этого класса, чтобы исследовать дальше. – Ray

+0

ByteStreams - это библиотека GoogleGuava для этого. Я думаю, вы оба здесь правы. Когда я шпионить класс, поведение преуспевает. Будем делать еще несколько исследований относительно того, какой метод это. –

ответ

2

Если вы посмотрите на реализацию ByteStreams, вы увидите, что используется (buf). В вашем случае он возвращает нуль, потому что для этого нет никакого определения определения, и это вызывает бесконечный цикл в экземпляре.

Вы можете либо изменить default mock behaviour, либо вручную добавить определение для read (buff).

1

Вы хотите настроить свой макет, чтобы назвать реальные методы InputStream, когда вы не погасили их

final InputStream mis = Mockito.mock(InputStream.class, Mockito.CALLS_REAL_METHODS); 

javadoc The состояние

Этой реализация может быть полезной при работе с устаревшим кодом. Когда используется , эта реализация используется, нераскрытые методы будут делегировать реальную реализацию . Это способ создания частичного макета объекта , который по умолчанию вызывает реальные методы.

Mockito, по умолчанию, издевается над всем. Метод ByteStreams#copy, который вы использовали, сначала вызывает InputStream#read(byte[]). Поскольку mockito издевался над ним, он вернет 0, который ByteStreams#copy интерпретирует как «есть больше, чтобы читать из этого потока» и продолжает читать (бесконечный цикл).

Используя Mockito.CALLS_REAL_METHODS, вы говорите Mockito, чтобы назвать фактическую реализацию в InputStream, которая будет делегировать до read(), которую вы зарезали, чтобы выбросить исключение.

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