Дразнить Runtime.getRuntime ()?

Может любой делать любые предложения о том, как лучше всего использовать EasyMock для ожидания вызова к Runtime.getRuntime().exec(xxx)?

Я мог переместить вызов в метод в другом классе, который реализует интерфейс, но быть бы в идеальном мире.

interface RuntimeWrapper {
    ProcessWrapper execute(String command) throws IOException;
}

interface ProcessWrapper {
    int waitFor() throws InterruptedException;
}

Я задавался вопросом, были ли у кого-либо какие-либо другие предложения?

15
задан Bozho 13 February 2010 в 14:48
поделиться

4 ответа

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

В качестве комментария я бы посоветовал посмотреть эту лекцию по объектно-ориентированному дизайну для проверки .

Обновление: Я не видел частного конструктора. Вы можете попробовать использовать инструментарий java-байт-кода , чтобы добавить еще один конструктор или сделать конструктор общедоступным, но это также может оказаться невозможным (если есть некоторые ограничения для этого класса).

Итак, ваш вариант - создать оболочку (как вы предложили в вопросе) и следовать подходу внедрения зависимостей.

14
ответ дан 1 December 2019 в 03:34
поделиться

Божо выше - это ИМО, правильное решение . Но это не единственное решение. Вы можете использовать PowerMock или JMockIt .

Использование PowerMock:

package playtest;

public class UsesRuntime {
    public void run() throws Exception {
        Runtime rt = Runtime.getRuntime();
        rt.exec("notepad");
    }
}


package playtest;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.legacy.PowerMockRunner;

import static org.powermock.api.easymock.PowerMock.*;
import static org.easymock.EasyMock.expect;

@RunWith(PowerMockRunner.class)
@PrepareForTest( { UsesRuntime.class })
public class TestUsesRuntime {

    @Test
    public void test() throws Exception {
        mockStatic(Runtime.class);
        Runtime mockedRuntime = createMock(Runtime.class);

        expect(Runtime.getRuntime()).andReturn(mockedRuntime);

        expect(mockedRuntime.exec("notepad")).andReturn(null);

        replay(Runtime.class, mockedRuntime);

        UsesRuntime sut = new UsesRuntime();
        sut.run();
    }
}
6
ответ дан 1 December 2019 в 03:34
поделиться

Райан Бейтс рассказал об этом в своей заставке «как добавить пользовательские маршруты, сделать некоторые параметры необязательными и добавить требования к другим параметрам». http://railscasts.com/episodes/70-custom-routes

-121--4268379-

Да, HashSet идеально подходит для этого, так как он содержит одно значение для поиска в отличие от словаря, который требует ключ и значение.

-121--1874183-

Возможно, вместо насмешек над Runtime.getRuntime () .exec () можно «поиздеваться» над сценарием/программой/и т.д. он должен был звонить.

Вместо передачи реальной последовательности командной строки в exec () запишите тестовый сценарий и выполните его вместо него. Сценарий может возвращать жестко закодированные значения, которые можно протестировать, как и издевательский класс.

1
ответ дан 1 December 2019 в 03:34
поделиться

Вот как вы могли бы сделать это с EasyMock 3.0 (и JUnit 4):

import org.junit.*;
import org.easymock.*;
import static org.easymock.EasyMock.*;

public final class EasyMockTest extends EasyMockSupport
{
    @Test
    public void mockRuntimeExec() throws Exception
    {
         Runtime r = createNiceMock(Runtime.class);

         expect(r.exec("command")).andReturn(null);
         replayAll();

         // In tested code:
         r.exec("command");

         verifyAll();
    }
}

Единственная проблема с выше теста является то, что время выполнения потребности объектов, которые будут переданы кода тестируемой, который предотвращает его использованием Runtime.getRuntime () . С JMockit , с другой стороны, следующий тест может быть написано, избегая этой проблемы:

import org.junit.*;
import mockit.*;

public final class JMockitTest
{
    @Test
    public void mockRuntimeExec() throws Exception
    {
        final Runtime r = Runtime.getRuntime();

        new NonStrictExpectations(r) {{ r.exec("command"); times = 1; }};

       // In tested code:
       Runtime.getRuntime().exec("command");
    }
}
0
ответ дан 1 December 2019 в 03:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: