насмешливый защищенный метод

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

package a;

public class A() {
    protected int m() {}
}

package b;

public class B extends a.A {
    // this class currently does not override m method from a.A
    public asd() {}
}

// test
package b;

class BTest {
    @Test
    public void testClass() {
        B instance = PowerMockito.spy(new B());
        PowerMockito.when(instance, <specify a method m>).thenReturn(123);
        //PowerMockito.when(instance.m()).thenReturn(123); -- obviously does not work
    }
}

Я посмотрел на переопределения PowerMockito.when, и кажется, что все они предназначены только для частных методов!

Как указать защищенный метод?


person michael nesterenko    schedule 29.11.2011    source источник
comment
@AndroidKiller, обновленный код с именем класса. На самом деле они могут быть из Mockito, но я использую powermock, и эти методы имеют там то же значение.   -  person michael nesterenko    schedule 29.11.2011
comment
Вот почему мы всегда должны предпочитать композицию наследованию. Если вы не можете просто переопределить этот метод в тестируемом коде, как вы это сделаете с устаревшим кодом.   -  person Brice    schedule 29.11.2011


Ответы (1)


В двух словах: не всегда можно использовать when, чтобы заглушить шпионов; используйте doReturn.

Предполагая статический импорт spy и doReturn (оба PowerMockito):

@RunWith(PowerMockRunner.class)
@PrepareForTest(B.class)
public class BTest {
    @Test public void testClass() throws Exception {
        B b = spy(new B());
        doReturn(42).when(b, "m");
        b.asd();
    }
}

Вы также можете @PrepareForTest(A.class) настроить doReturn на when(a, "m"). Что имеет больше смысла, зависит от фактического теста.

person Dave Newton    schedule 29.11.2011
comment
вау, спасибо. Интересно, что когда я попытался использовать экземпляр метода вместо имени строки метода, заглушка не удалась с сообщением об исключении о неправильном количестве аргументов. Но со строковым именем все работает отлично. - person michael nesterenko; 29.11.2011
comment
@mishanesterenko Да, иногда это может быть немного запутанным. Другим вариантом всегда является создание подкласса B для целей теста. Не всегда вариант, но менее волшебный, чем изменение байт-кода;) - person Dave Newton; 29.11.2011
comment
Что бы вы сделали, если бы вы установили Methode, возвращающий void. Допустим, m - это set-Methode, такой как void m (парсер MySpecialParser). Этот парсер используется для разбора моего текста. Как я могу издеваться над этим? - person Kayser; 19.09.2012
comment
@Kayser Разве нет ничего не делать? Я не помню навскидку. - person Dave Newton; 19.09.2012
comment
Хороший ответ. FWIW: это в значительной степени следует соглашению из документа PowerMock (полный пример частичное издевательство над разделом частного метода относится и к защищенному). - person cellepo; 25.04.2014