2012-06-01 2 views
6

У меня есть класс, где Runtime.getRuntime() используется для выполнения сценария из командной строки и получения результата для дальнейшей обработки.Как обойти Runtime.getRuntime() при записи JUnit?

Но когда я пишу JUnit для этого класса, я не могу найти способ издеваться/избегать этого Runtime.getRuntime(). Exec().

Я не могу использовать EasyMock или PowerMock или любые другие макеты api, кроме Mockito.

Пожалуйста, дайте мне способ преодолеть эту проблему, потому что это влияет на покрытие кода.

ответ

13

Необходимо рефакторинг. Экстракт Runtime.getRuntime().exec() в отдельный класс:

public class Shell { 

    public Process exec(String command) { 
    return Runtime.getRuntime().exec(command); 
    } 

} 

Теперь InstEd вызова getRuntime() явно вводить Shell класс как-то к классу испытуемый:

public class Foo { 

    private final Shell shell; 

    public Foo(Shell shell) { 
    this.shell = shell; 
    } 

    //... 
    shell.exec(...) 

} 

В тесте JUnit просто вводят высмеивал Shell класс, передав его в конструктор :

@Mock 
private Shell shellMock; 

new Foo(shellMock); 

Сидней: да, я не создание интерфейса Shell с одной реализацией. Вы не возражаете? Мокито - нет. Бонус: теперь вы можете проверить, если правильный процесс был назван:

verify(shellMock).exec("/usr/bin/gimp"); 
+0

HI, Спасибо за быстрый ответ !! – unni

+0

Но все еще есть какой-то другой способ? Где мне не нужно менять конструктор? Не используйте сеттер, например 'this.shell = shell;' – unni

+0

@ user1147417: Я не вижу никакой возможности, по крайней мере, без PowerMock. 'статические' злые! –

3

Tomasz Nurkiewicz предоставил замечательный ответ. Но есть альтернатива.

Вы можете переместить Runtime.getRuntime() в свой собственный метод в классе, который вы тестируете; затем проверьте его шпионами Mockito. В шпионах Mockito вы можете переопределить этот конкретный метод версией, которая создает макет Runtime, а затем делать с ним все, что вам нравится.

Однако подход Томаша более чист, и я рекомендую его тщательно. Я просто хотел сказать, что есть другой способ сделать это, не прибегая к Powermock.

+0

oops David, я не видел вашего ответа, прежде чем публиковать его снова. Большое спасибо за предоставление прекрасного решения. – unni

0

я суб-причислять и наиважнейшая (как описано в книге Michael C. Перья эффективно Работа с унаследованным кодом ")

Предположим, что мы имеем следующий код:

public class CannotChange{ 
    public CannotChange(){} 
    public void TryingToTest() throws IOException { 
     ... 
     Process proc = Runtime.getRuntime().exec("command"); 
     ... 
    } 
} 

Extract исполняющую код в защищенный метод:

public void TryingToTest() throws IOException { 
     ... 
     Process proc = execute("command"); 
     ... 
    } 
    protected Process execute(string command){ 
     return Runtime.getRuntime().exec(command); 
    }  

Затем в тестовом классе создать класс, который расширяет класс CannotChange и переопределяет выполнить

public class CannotChangeTest{ 

    private class CannotChangeForTesting extends CannotChange{ 
     public CannotChangeForTesting(){ super(); } 
     @Override 
     public Process execute(String command){ 
     return null; //or a mocked object 
     } 
    } 

    @Test 
    public void TestMethod(){ 
     CannotChange cannotChange = new ForTestCannotChange(); 
     cannotChange.TryingToTest(); 
    } 
} 
Смежные вопросы