Как смоделировать метод getResourceAsStream с помощью PowerMockito и JUnit?

Я пытаюсь издеваться над методом getResourceAsStream, который я вызываю в конструкторе.

public Conn() {
    stream = Conn.class.getClass().getResourceAsStream(PATH);
}

Для mock framework я предпочитаю Mockito + PowerMockito.

    @RunWith(PowerMockRunner.class)
    @PrepareForTest(Conn.class)
    public class ConnTest {

        @Mock
        private InputStream streamMock;

        private Conn conn;

        @Before
        public void before() {
            initMocks(this);
        }

        @Test
        public void test() {    
            PowerMockito.mockStatic(Conn.class);
            PowerMockito.when(Connector.class.getResourceAsStream("/prop.properties")).thenReturn(streamMock);
            conn = new Conn();
        }

        @After
        public void after() {
            reset(streamMock);
        }
     }

Но метод thenReturn не возвращает макет. Как я могу это исправить?


person barbara    schedule 13.03.2015    source источник


Ответы (3)


Вы можете абстрагироваться от получения ресурса в класс.

class StreamFetcher {

InputStream fetchStream(String path) {
return StreamFetcher.class.getClass().getResourceAsStream(path);
}

}

и в вашем классе

class Conn {
public Conn(StreamFetcher streamFetcher) {
    stream = streamFetcher.fetchStream(PATH);
}
}

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

Также вы можете больше абстрагироваться и, возможно, как-то обработать поток. Я не знаю бизнес-контекста, поэтому не могу вам помочь в этом.

person Marcin Grzejszczak    schedule 12.09.2015

Он не возвращает макет, потому что тестируемый код new Conn() не вызывает

Connector.class.getResourceAsStream(...)

это звонит

Conn.class.getResourceAsStream(...)

Ваш код работал, изменив метод заглушки на:

PowerMockito.when(Conn.class.getResourceAsStream("/prop.properties")).thenReturn(streamMock);
person Jose Tepedino    schedule 22.09.2015

Вы можете сделать, как показано ниже:

    @RunWith(PowerMockRunner.class)
    @PrepareForTest(Class.class)
    public class ConnTest {

        @Mock
        private InputStream streamMock;

        private Conn conn;

        @Before
        public void before() {
            initMocks(this);
        }

        @Test
        public void test() {    
            PowerMockito.mockStatic(Class.class);
            PowerMockito.when(Connector.class.getClass().getResourceAsStream("/prop.properties")).thenReturn(streamMock);
            conn = new Conn();
        }

        @After
        public void after() {
            reset(streamMock);
        }
     }

Здесь вы размещаете ресурс поверх объекта класса, поэтому Class.class вам нужно подготовиться к тесту, используя @PrepareForTest(Class.class) и PowerMockito.mockStatic(Class.class);.

Я не уверен, будет ли это работать для конструктора или нет, но для метода, который вызывает getClass.getResourceAsStream("anyString"), он работает нормально (я проверял).

person Chandra Sekhar    schedule 11.08.2016