Как я могу имитировать частный статический метод с помощью PowerMockito?

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

PowerMockito.spy(StaticUtil.class);
PowerMockito.when(StaticUtil.class, "getSomethingMethod", someObjectArray, someStringArray, aBoolean, someList).thenReturn(anotherList);

Я получаю исключение с нулевым указателем, потому что действительно вызывается getSomethingMethod(). Когда я отлаживаю, я вижу, что он не вызывается, когда я запускаю метод, который пытаюсь протестировать, но он работает, когда я настраиваю макет. Судя по этому сайту, похоже, что именно это и должно произойти, когда вы создаете макет в этом формат.

Итак, я пытаюсь настроить макет таким образом:

PowerMockito.spy(StaticUtil.class);        
PowerMockito.doReturn(anotherList).when(StaticUtil.getSomethingMethod( someObjectArray, someStringArray, aBoolean, someList);

Однако я получаю сообщение об ошибке от Eclipse, в котором говорится, что мне нужно изменить видимость getSomethingMethod() на общедоступную. Не является ли одно из больших преимуществ использования PowerMockito в том, что вы можете имитировать частные методы? Мне нужно издеваться над этим private static методом (без фактического вызова метода во время настройки).


person user3897392    schedule 03.08.2015    source источник
comment
Не могли бы вы вставить еще код ваших тестов? Правильно ли подготовлен ваш тестовый класс к насмешкам над властью?   -  person Karol Lewandowski    schedule 04.08.2015
comment
Дикая догадка, у тебя нет @PrepareForTest   -  person    schedule 04.08.2015


Ответы (2)


Вы должны использовать точный синтаксис, указанный в ответе, который вы связали. Этот синтаксис - doReturn(returnValue).when(Class, String, arguments);. Ни один из приведенных здесь примеров не использует этот пример.


Вот расширенное объяснение. Я собрал образец тестовой среды, чтобы продемонстрировать это:

Попытка запустить тесты на этом классе:

package org.test.stackoverflow;

import java.util.Collections;
import java.util.List;

public class StaticUtil {
  public static void Wrapper() {
    getSomethingMethod(null, null, false, Collections.<String>emptyList());
  }

  private static List<String> getSomethingMethod(Object[] obj,
      String[] str, boolean flag, List<String> aList){ 
    System.out.println("I happen!");
    return aList;
  }
}

Если будет вызван сам метод, мы увидим I happen!. Если этого не произойдет, мы не будем.

Затем я использую этот тестовый класс:

package org.test.stackoverflow;

import java.util.List;

import org.junit.runner.RunWith;
import org.junit.*;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest(org.test.stackoverflow.StaticUtil.class)
public class StaticUtilTest {
  Object[] someObjectArray;
  String[] someStringArray;
  boolean aBoolean;
  List<String> someList;
  List<String> anotherList;

  @Test
  public void testWhenClassStringMethod() throws Exception {
    System.out.println("Beginning Test when(Class klass, String method name).doReturn(result)");
    PowerMockito.spy(StaticUtil.class);
    PowerMockito.when(StaticUtil.class, "getSomethingMethod", someObjectArray, someStringArray, aBoolean, someList).thenReturn(anotherList);
    System.out.println("End Test when");
  }

  @Test
  public void testDoReturnActualMethod() throws Exception {
    PowerMockito.spy(StaticUtil.class);
    // This doesn't compile as you've correctly stated
//    PowerMockito.doReturn(anotherList).when(StaticUtil.getSomethingMethod(someObjectArray, someStringArray, aBoolean, someList);
  }

  @Test
  public void testDoReturnClassStringMethod() throws Exception {
    System.out.println("Beginning Test doReturn().when(Class klass, String method name");
    PowerMockito.spy(StaticUtil.class);
    PowerMockito.doReturn(anotherList).when(StaticUtil.class, "getSomethingMethod", someObjectArray, someStringArray, aBoolean, someList);
    System.out.println("End Test doReturn");
  }
}

Итак, если он печатает I happen, значит, мы использовали неправильный синтаксис. Когда я запускаю эту программу, мы получаем:

Beginning Test when(Class klass, String method name).doReturn(result)
I happen!
End Test when
Beginning Test doReturn().when(Class klass, String method name)
End Test doReturn

Следовательно, вы должны использовать синтаксис в третьем тесте.

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

person durron597    schedule 03.08.2015
comment
Большое спасибо за подробный ответ, я потратил на это столько времени! Синтаксис в третьем тесте работал отлично. СПАСИБО СПАСИБО СПАСИБО! - person user3897392; 04.08.2015
comment
Как сработал третий тест? 'Я случается!' строка не печатается, это не означает, что насмешка настроена правильно. здесь вы пытались издеваться над классом StaticUtil, но не вызывали оболочку тестового метода. см. мой другой ответ. - person kswaughs; 05.08.2015

когда вы устанавливаете ожидания для фиктивного объекта, вы должны использовать сопоставители аргументов, такие как Matchers.any () или Matchers.anyString (), но не фактические аргументы.

Подробнее см. Мой ответ на J-Unit Test: сделать статический метод void в исключении выброса окончательного класса

Существует потенциальная проблема с ответом durron597.: синтаксис в testDoReturnClassStringMethod не имитируется должным образом. В этом методе он попытался имитировать класс StaticUtil, но не вызвал оболочку тестового метода. См. Пример

@Test
public void testDoReturnClassStringMethod() throws Exception {
    System.out.println("Beginning Test doReturn().when(Class klass, String method name");
    PowerMockito.spy(StaticUtil.class);
    PowerMockito.doReturn(anotherList).when(StaticUtil.class, "getSomethingMethod", someObjectArray, someStringArray, aBoolean, someList);
    StaticUtil.Wrapper();
    System.out.println("End Test doReturn");
}

Результат для этого

Beginning Test doReturn().when(Class klass, String method name
I happen!
End Test doReturn

'Я случается!' печатается. макет настроен неправильно.

Правильный способ издевательства:

@Test
public void testDoReturnWithProperMock() throws Exception {
    System.out.println("Beginning Test doReturn().when(Class klass, String method name");
    PowerMockito.spy(StaticUtil.class);
    PowerMockito.doReturn(anotherList).when(StaticUtil.class, "getSomethingMethod", Matchers.anyObject(), Matchers.anyObject(), Matchers.anyBoolean(), Matchers.anyList());
    StaticUtil.Wrapper();
    System.out.println("End Test doReturn");

}

Для чего результат:

Beginning Test doReturn().when(Class klass, String method name
End Test doReturn
person kswaughs    schedule 04.08.2015
comment
Голосующий против, пожалуйста, обновите причину, по которой проголосовал против правильного ответа - person kswaughs; 05.08.2015
comment
Это пограничный ответ, содержащий только ссылку. Вам следует расширить свой ответ, включив сюда как можно больше информации, и использовать ссылку только для справки. - person Kyll; 05.08.2015
comment
Это ответ только для ссылки на другой вопрос SO, на который ответил @kswaughs. Либо здесь необходимо перенести соответствующую информацию, либо этот вопрос следует пометить как дубликат связанного вопроса. - person dcsohl; 05.08.2015
comment
@kswaughs Сначала вы отправили этот ответ, а затем отправили второй ответ. Вы могли бы отредактировать этот (1-й) ответ и добавить дополнительную информацию. См. Ссылку редактирования под вашим ответом. Ваша ссылка также является еще одним ответом на переполнение стека, и если это отвечает на этот вопрос, возможно, это дубликат? См. Этот вопрос: Что нам делать с ответами, которые являются просто ссылками на другие ответы на Stack Overflow? :) - person James; 05.08.2015