2014-11-13 2 views
0

Я получил следующий код:Байтмен JUnit Runner - невозможно, чтобы вызвать IOException на авто-замкнутый InputStream # близко

Collection<String> errors = ...; 
try (InputStream stream = My.class.getResourceAsStream(resource)) { 
    // do stuff 
} 
catch(IOException ex) { 
    errors.add("Fail"); 
} 

Я пытаюсь с Байтмен JUnit Runner, чтобы вызвать IOException, когда (действительный) входной поток даю якобы закрыт:

@RunWith(BMUnitRunner.class) 
public class MyTest { 

    private My my = new My(); 

    @BMRule(
     name = "force_read_error", 
     targetClass = "java.io.InputStream", 
     targetMethod = "close()", 
     action = "throw new IOException(\"bazinga\")" 
    ) 
    @Test 
    public void catches_read_error() throws IOException { 
     Collection<String> errors = my.foo("/valid-resource-in-classpath"); 

     assertThat(errors).containsExactly("Fail"); 
    } 
} 

Мой тест не: ошибки всегда пусто, что означает Байтмен правило, очевидно, не выполняется (это хорошо загружен агентом, так что я не понимаю, что происходит).

Как я могу вызвать метод IOException при закрытии, вызванный через try-with-resources?

ответ

1

Ваше правило IST не стрелять, потому что класс объекта потока, полученные при вызове

InputStream stream = My.class.getResourceAsStream(resource) 

не является классом «java.io.InputStream». Это класс , расширяющий «java.io.InputStream», скорее всего, «BufferedInputStream».

Рассказывать Байтмен к «правилу триггера для любого класса, простирающейся java.io.InputStream», вам нужно поставить «^» перед именем класса:

targetClass = "^java.io.InputStream" 

Это изменение может иметь нежелательный побочный эффект , что правило запускается также, когда другие объекты, расширяющие «java.io.InputStream», закрываются. Чтобы этого не произошло, условие должно быть добавлено в правило только для запуска, когда вызывающий абонент соответствует методу «foo» класса «Мой». Байтмен имеет вспомогательный метод для того, что называют «callerMatches» (Please see also the advanced tutorial)

рабочим состоянием для Вашего случая будет:

condition = "callerMatches(\".+My.foo\",true,true)" 

Полное определение правила Байтмена в BMRule аннотации должно выглядеть следующим образом:

@BMRule(
    name = "force_read_error", 
    targetClass = "^java.io.InputStream", 
    targetMethod = "close()", 
    condition = "callerMatches(\".+My.foo\",true,true)", 
    action = "throw new java.io.IOException(\"bazinga\")" 
) 
Смежные вопросы