Класс тестирования с защищенным конструктором с PowerMock и Mockito

У меня есть следующий класс для тестирования:

public abstract class Challenge {
    protected int id;
    protected String name;
    protected String question;

    protected Challenge(){}

    public String[] toStrings(){
        String[] s = {Integer.toString(id), name, question};
        return s; 
    }

    ...

Но с помощью этого теста:

@Test
public void testToStrings() throws Exception{

    String[] expectedResult1 = new String[]{"1", "a", "b"};

    String[] obtainedResult1 = null;

    Challenge challengeMock = PowerMockito.mock(Challenge.class);
    challengeMock.id = 1;
    challengeMock.name = "a";
    challengeMock.question = "b";

    obtainedResult1 = challengeMock.toStrings();
    Assert.assertEquals(expectedResult1[0], obtainedResult1[0]);
    Assert.assertEquals(expectedResult1[1], obtainedResult1[1]);
    Assert.assertEquals(expectedResult1[2], obtainedResult1[2]);
}

Я получаю NullPointerException из-за "obtainedResult1 = challengeMock.toStrings();" который возвращает ноль.

Я использую PowerMock + Mockito, работающий в Robolectric с правилом (потому что это проект для Android).

@Rule
public PowerMockRule rule = new PowerMockRule();

В чем проблема?


person DkSw    schedule 25.03.2012    source источник
comment
Зачем вам издеваться над тестируемым классом? Возможно, вы хотите использовать PowerMockito.spy() или попытаться создать (анонимную) реализацию Challenge.   -  person nansen    schedule 25.03.2012
comment
Я издевался над этим только потому, что было проще использовать приватный конструктор и устанавливать приватные данные. Любые советы по использованию шпиона, пример может быть?   -  person DkSw    schedule 26.03.2012
comment
К вашему сведению, хотя Дэвид уже ответил на ваш вопрос: шпион похож на макет, но обычно используется для насмешки или проверки определенного поведения фактического CUT. Вы можете использовать его как макет (Mockito.spy(CUT.class)) или с аннотациями. эквивалентный метод предлагается PowerMockito. Я стараюсь вообще не использовать powermock, так как обычно считаю его необходимость признаком плохого дизайна, то есть нетестируемости. Но это личный вкус.   -  person nansen    schedule 26.03.2012
comment
Спасибо за ваше предложение. Я использую powermock только потому, что у меня есть несколько статических конечных методов и абстрактный класс, поэтому я тоже могу их протестировать. Кстати, у меня очень близкий крайний срок, поэтому решение с real_method быстрее. Для следующего проекта я, конечно же, лучше изучу тестирование и использование шпиона.   -  person DkSw    schedule 27.03.2012


Ответы (1)


Для этого вам не нужен PowerMock; макет Mockito будет в самый раз. Но обычно макет не имеет функциональности в своих методах, поэтому toStrings() не возвращает ожидаемое значение. Чтобы изменить это, вам нужен ответ по умолчанию CALLS_REAL_METHODS.

Поэтому я бы порекомендовал изменить строку, в которой вы создаете макет (третья непустая строка testToStrings), на что-то вроде этого.

Challenge challengeMock = Mockito.mock(Challenge.class, Mockito.CALLS_REAL_METHODS );

Я проверил это, и ваш тест проходит, если вы внесете это изменение.

person Dawood ibn Kareem    schedule 26.03.2012