Robolectric + PowerMock + Mockito не работает

Я изо всех сил пытаюсь получить эту редкую комбинацию, но мне не повезло. Мой проект использует JUnit + Mockito + Robolectric для тестирования и Roboguice для инъекций, когда я добавил PowerMock в уравнение, происходили странные вещи, вот некоторые из вещей, которые я пробовал:

1.- Интеграция PowerMock + Mockito + Robolectic из коробки. Как было предложено в PowerMockIngration, я добавил @PowerMockRunnerDelegate, чтобы включить свой собственный бегун, который расширяется от RobolectricGradleTestRunner:

Build.gradle

  testCompile 'org.powermock:powermock-module-junit4:1.6.4'
  testCompile 'org.powermock:powermock-api-mockito:1.6.4'

Контрольная работа

@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(MyCustomRunner.class)
@Config(constants = BuildConfig.class)
@PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*"})
@PrepareForTest(RoboGuice.class)
public class Test {

  @Before
  public void setUp() throws Exception {
    PowerMockito.mockStatic(RoboGuice.class);
    ....
  }

Результат:

java.lang.IllegalArgumentException: Cannot subclass final class class roboguice.RoboGuice at org.mockito.cglib.proxy.Enhancer.generateClass(Enhancer.java:447) 
 at org.mockito.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
    at org.mockito.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:217)
    at org.mockito.cglib.proxy.Enhancer.createHelper(Enhancer.java:378)
    at org.mockito.cglib.proxy.Enhancer.createClass(Enhancer.java:318)
    at org.powermock.api.mockito.repackaged.ClassImposterizer.createProxyClass(ClassImposterizer.java:123)
    at org.powermock.api.mockito.repackaged.ClassImposterizer.imposterise(ClassImposterizer.java:57)
    at org.powermock.api.mockito.internal.mockcreation.MockCreator.createMethodInvocationControl(MockCreator.java:111)
    at org.powermock.api.mockito.internal.mockcreation.MockCreator.mock(MockCreator.java:59)
    at org.powermock.api.mockito.PowerMockito.mockStatic(PowerMockito.java:70)
    at com.humana.vitalityapp.activity.BaseVitalityActivityTest.setUp(BaseVitalityActivityTest.java:79)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
    at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:251)
    at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:188)
    at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:54)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:152)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner$2.call(DelegatingPowerMockRunner.java:146)
    at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner$2.call(DelegatingPowerMockRunner.java:139)
    at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner.withContextClassLoader(DelegatingPowerMockRunner.java:130)
    at org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner.run(DelegatingPowerMockRunner.java:139)
    at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:106)
    at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
    at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:59)...

Это похоже на то, что @PrepareForTest не работает, тогда я попробовал, когда правило, загрузчик классов, как предлагается в том же руководстве:

Build.gradle

  testCompile 'org.powermock:powermock-module-junit4:1.6.4'
  testCompile "org.powermock:powermock-module-junit4-rule:1.6.4"
  testCompile 'org.powermock:powermock-api-mockito:1.6.4'
  testCompile "org.powermock:powermock-classloading-xstream:1.6.4"

Тестовый класс

@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(MyCustomRunner.class)
@Config(constants = BuildConfig.class)
@PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*"})
@PrepareForTest(RoboGuice.class)
public class Test { 
  @Rule public PowerMockRule rule = new PowerMockRule();

@Before
  public void setUp() throws Exception {
    PowerMockito.mockStatic(RoboGuice.class);
   ...
  }

На этом этапе тест проходит, и я смог смоделировать RoboGuice, как и ожидалось, НО, когда я запустил все свои тестовые примеры вместе, я начинаю получать следующее исключение при создании простого макета типа mock(OtherClass.class):

org.mockito.exceptions.base.MockitoException: 
ClassCastException occurred while creating the mockito proxy :
  class to mock : 'com.humana.vitalityapp.analytics.Analytics', loaded by classloader : 'org.powermock.core.classloader.MockClassLoader@168fa63d'
  created class : 'com.humana.vitalityapp.analytics.Analytics$$EnhancerByMockitoWithCGLIB$$67cb81b1', loaded by classloader : 'org.mockito.internal.creation.util.SearchingClassLoader@20f5a6b6'
  proxy instance class : 'com.humana.vitalityapp.analytics.Analytics$$EnhancerByMockitoWithCGLIB$$67cb81b1', loaded by classloader : 'org.robolectric.internal.bytecode.InstrumentingClassLoader@6fdbe764'
  instance creation by : ObjenesisInstantiator

You might experience classloading issues, disabling the Objenesis cache *might* help (see MockitoConfiguration)

    at com.humana.vitalityapp.activity.BaseVitalityActivityTest.setUp(BaseVitalityActivityTest.java:77)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
    at org.powermock.modules.junit4.rule.PowerMockStatement$1.run(PowerMockRule.java:65)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)

Итак, я перепробовал множество вариантов: Удалить загрузчик классов xtream:

  java.lang.RuntimeException: java.lang.ClassNotFoundException: org.powermock.classloading.DeepCloner

    at org.powermock.api.support.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:68)
    at org.powermock.api.support.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:34)

Пользователь JunitAgent:

 testCompile 'org.powermock:powermock-module-junit4:1.6.4'
  testCompile "org.powermock:powermock-module-junit4-rule-agent:1.6.4"
  testCompile 'org.powermock:powermock-api-mockito:1.6.4'

Caused by: java.lang.IllegalStateException: PowerMockRule can only be used with the system classloader but was loaded by org.robolectric.internal.bytecode.InstrumentingClassLoader@2a7f1f10

Итак, у меня заканчиваются идеи, кто-нибудь ??


person JavierSP1209    schedule 22.03.2016    source источник
comment
Большое усилие, чтобы заставить эту установку работать. К счастью, я не очень люблю PowerMock, поэтому не использую его. К сожалению, я тоже не знаю, как заставить его работать. Это рекомендуемый способ тестирования вещей RoboGuice?   -  person Eugen Martynov    schedule 24.03.2016
comment
Ну, я только добавляю новую BaseActivity для своего проекта, потому что я обновляюсь, чтобы использовать AppCompat, поэтому моя новая активность расширяется от нее, и я пытаюсь внедрить в нее все, и она работает, я просто хотел протестировать этот класс, другой способ, который я пробовал, - это обертывание RoboGuice.getInjector в провайдере, таким образом я мог все протестировать, я просто пытался использовать PowerMock, чтобы избежать создания провайдеров для статического класса, поскольку он теряет преимущества статических методов   -  person JavierSP1209    schedule 24.03.2016
comment
Можете попробовать рекомендуемый способ? В этом случае powermock не нужен.   -  person Eugen Martynov    schedule 24.03.2016
comment
Вы имеете в виду рекомендуемый способ добавления провайдера? Если это так, да, я сделал это, и его работа Я просто пытался настроить PowerMock для имитации статических методов в приложении, проблема такая же, когда у вас есть последний класс, и вы пытаетесь имитировать его и использовать PowerMock / RobolectricRunner вместе   -  person JavierSP1209    schedule 24.03.2016
comment
Ага, мне нужно быть более сосредоточенным. Какой статический вызов вы пытаетесь высмеять? Может есть другой способ проверить это. С провайдером вам не нужно статически имитировать RoboGuice, верно?   -  person Eugen Martynov    schedule 24.03.2016
comment
Да, правильно, потому что я могу ввести или установить поставщика и заглушить его как обычный класс с помощью Mockito, но, по крайней мере, для меня я люблю использовать статические методы, когда это возможно.   -  person JavierSP1209    schedule 24.03.2016
comment
Я бы поспорил, но это дело вкуса. Статический всегда усложняет тестирование или код уязвим для модификаций.   -  person Eugen Martynov    schedule 24.03.2016


Ответы (1)


У меня такая же проблема.

Мое решение было:

  • удалить testCompile "org.powermock:powermock-module-junit4-rule-agent:x.x.x" из градиента

  • измените import static * .Mockito.mock и * .Mockito.when на org.powermock.api.mockito.PowerMockito.mock и org.powermock.api.mockito.PowerMockito.when.

person Mateusz Dziekan    schedule 06.12.2017