Powermock: издевательский метод все еще вызывается

#java #unit-testing #junit4 #powermock

#java #модульное тестирование #junit4 #powermock

Вопрос:

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

Я использую JUnit4 и Powermock 1.5.5 (с mockito 1.9.5)

Моя проблема заключается в следующем: в моих модульных тестах мне нужно издеваться над статическим методом в классе, который я не могу изменить. Я хочу издеваться только над одним методом, а не над всем классом, поэтому я пошел на шпиона.

Вот что у меня есть до сих пор :

 [...]
import static org.mockito.Matchers.*;
import static org.powermock.api.mockito.PowerMockito.*;

@RunWith(JUnitParamsRunner.class)
@ContextConfiguration(locations={"classpath:applicationContext-test.xml"},
    loader=MockWebApplicationContextLoader.class)
@MockWebApplication(name="my-app")
@PrepareForTest(value = {
    Role.class
})
public class MyTest {

    @Rule
    public PowerMockRule powerMockRule = new PowerMockRule();

    @Before
    public void setUp() throws Exception {
        initSpring();
        mockRoleServices();
    }

    private void mockRoleServices() throws Exception {
        spy(Role.class);
        RoleAnswer roleAnswer = new RoleAnswer(RoleEnum.ADMIN);
        when(Role.hasAdministratorRole(anyLong(), anyLong(), anyLong()))
            .then(roleAnswer);
    }

    private class RoleAnswer implements Answer<Boolean> {

        private RoleEnum roleEnum;

        private RoleAnswer(RoleEnum roleEnum) {
            this.roleEnum = roleEnum;
        }

        @Override
        public Boolean answer(InvocationOnMock invocation) throws Throwable {
            return getRenderRequest().getUserRole() != null amp;amp;
                    getRenderRequest().getUserRole().equals(roleEnum);
        }
    }
}
  

Вот проблема: метод Role.hasAdministratorRole() вызывается вместо того, чтобы издеваться

Вот что я пробовал до сих пор :

  • Использование mockStatic(Role.class) вместо spy() метода. Как и ожидалось, все методы издеваются, поэтому я в конечном итоге получаю NPE перед Role.hasAdministratorRole() вызовом
  • Делаю что-то вроде doAnswer(...).when(...) . Я получаю сообщение об ошибке во время выполнения с помощью powermock, сообщающего мне, что мой макет не завершен (что фактически подтверждает, что что-то не так либо с моим кодом, либо с самой библиотекой)
  • Попытка объявить метод по его имени, а не вызывать его напрямую: when(Role.class, "hasAdministratorRole", long.class, long.class, long.class) . То же поведение
  • Куча других вещей, которые я больше не помню.

Ваша помощь будет высоко оценена. Спасибо!

РЕДАКТИРОВАТЬ: благодаря ответу Шрикантлингалы я смог точно определить проблему.

Это не сработало :

 when(Role.hasAdministratorRole(anyLong(), anyLong(), anyLong()))
    .thenAnswer(roleAnswer);
  

но это сделало :

 doAnswer(roleAnswer).when(Role.class, "hasSiteAdministratorRole",
    anyLong(), anyLong(), anyLong());
  

Итак, переключение тогда when() и answer() сработало

Комментарии:

1. Кроме того, я отметил, что класс, который я пытаюсь издеваться, находится в jar в пути к классу (т.Е. Не Непосредственно в пути к классу). Может ли это иметь отношение к делу?

2. Может быть, это потому, что вы не запускаете тест с помощью PowerMockRunner?

3. Другие издевательства работают, потому что я использую PowerMockRule. Но в любом случае, я протестировал его, и я получил точно такой же результат: (

Ответ №1:

Поскольку у меня нет всех ваших реализаций, я настроил несколько фиктивных реализаций и сделал аналогичную настройку, подобную вашей. Приведенный ниже код отлично работает для меня.

 import static junit.framework.Assert.assertTrue;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest(value = {
    Role.class
})
public class RoleTest {

    @Test
    public void mockRoleServices() throws Exception {
        PowerMockito.spy(Role.class);
        PowerMockito.doAnswer(new RoleAnswer(RoleEnum.ADMIN)).when(Role.class, "hasAdministratorRole", Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong());

        Role.printOut();

        assertTrue(Role.hasAdministratorRole(1, 1, 1));
    }

    private class RoleAnswer implements Answer<Boolean> {

        private RoleEnum roleEnum;

        private RoleAnswer(RoleEnum roleEnum) {
            this.roleEnum = roleEnum;
        }

        public Boolean answer(InvocationOnMock invocation) throws Throwable {
            return true;
        }
    }
}
  

Фиктивный класс роли:

 public class Role {

    public static Boolean hasAdministratorRole(long a, long b, long c) {
        System.out.println("Inside hasAdministratorRole");
        return a   b   c < 0;
    }

    public static void printOut() {
        System.out.println("Inside Printout");
    }

}
  

Мой тестовый пример не распечатывается Inside hasAdministratorRole , а распечатывается Inside Printout

Надеюсь, это поможет

Комментарии:

1. Большое спасибо, что нашли время для его тестирования. Я смог заставить его работать с классами непосредственно в моем пути к классам (т. Е. Не В jar). Не могли бы вы, пожалуйста, попытаться поместить свои фиктивные классы в jar и повторно протестировать их? Я начинаю думать, что проблема в этом.

2. У меня отлично работает даже из jar.

3. Спасибо за ваш ответ, я смог заставить его работать. Я отредактировал свой вопрос, чтобы добавить ответ, но я действительно не понимаю, почему это работает. У вас есть подсказка? Еще раз спасибо за вашу драгоценную помощь

Ответ №2:

Рад, что вы решили свою проблему, это просто предупреждение для всех остальных, имеющих аналогичную проблему.

Настройка проекта:

  • Powermock 1.5.5
  • Mockito 1.9.5
  • TestNG 6.8.8

Powermock не учитывает макеты / шпионы, созданные в методе, аннотированном @BeforeTest

Например.:

 @BeforeTest
public void setup(){
    testee = mock(AClass.class);
}
  

Он отбрасывается, а затем вводит издевательский метод вместо того, чтобы возвращать ожидаемый результат ИЛИ выдавать всевозможные странные исключения. При переходе к общему методу тестирования он внезапно начинает работать:

 @Test
public void test(){
    AClass testee = mock(AClass.class);
    ....
}
  

Возможно, это ошибка.

Комментарии:

1. Возникла проблема: code.google.com/p/powermock/issues /…