2014-09-15 2 views
7

Согласно the PowerMock docs, я должен работать с PowerMockRule вместо @RunWith(PowerMockRunner.class) и получать те же результаты.Можно ли издеваться над статическим методом в конечном классе, используя PowerMockRule вместо PowerMockRunner?

Кажется, я нашел случай, когда это неверно.

Ниже пример работает нормально:

package com.test.powermockstatics; 

import static org.junit.Assert.assertEquals; 
import static org.powermock.api.mockito.PowerMockito.mockStatic; 
import static org.powermock.api.mockito.PowerMockito.when; 

import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.powermock.core.classloader.annotations.PrepareForTest; 
import org.powermock.modules.junit4.PowerMockRunner; 

final class FinalClassWithStaticCall { 
    public static int getIntStatic() { 
    return 1; 
    } 
} 

@RunWith(PowerMockRunner.class) 
@PrepareForTest(FinalClassWithStaticCall.class) 
public class TestStaticMockingWithoutPowerMockRunner { 
    @Test 
    public void testStaticCall() { 
    mockStatic(FinalClassWithStaticCall.class); 
    when(FinalClassWithStaticCall.getIntStatic()).thenReturn(2); 

    assertEquals(FinalClassWithStaticCall.getIntStatic(), 2); 
    } 
} 

Но при переключении на правило так:

package com.test.powermockstatics; 

import static org.junit.Assert.assertEquals; 
import static org.powermock.api.mockito.PowerMockito.mockStatic; 
import static org.powermock.api.mockito.PowerMockito.when; 

import org.junit.Rule; 
import org.junit.Test; 
import org.powermock.core.classloader.annotations.PrepareForTest; 
import org.powermock.modules.agent.PowerMockAgent; 
import org.powermock.modules.junit4.rule.PowerMockRule; 

final class FinalClassWithStaticCall { 
    public static int getIntStatic() { 
    return 1; 
    } 
} 

@PrepareForTest(FinalClassWithStaticCall.class) 
public class TestStaticMockingWithoutPowerMockRunner { 
    static { 
    PowerMockAgent.initializeIfNeeded(); 
    } 

    @Rule 
    public PowerMockRule rule = new PowerMockRule(); 

    @Test 
    public void testStaticCall() { 
    mockStatic(FinalClassWithStaticCall.class); 
    when(FinalClassWithStaticCall.getIntStatic()).thenReturn(2); 

    assertEquals(FinalClassWithStaticCall.getIntStatic(), 2); 
    } 
} 

я получаю следующее исключение:

java.lang.IllegalArgumentException : Не может подкласс класса конечного класса com.test.powermockstatics.FinalClassWithStaticCall по адресу org.mockito.cglib.proxy.Enhancer.generateClass (Enhancer.java:447) в 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) на org.mockito.internal.creation.jmock.ClassImposterizer.createProxyClass (ClassImposterizer.java:110) на org.mockito.internal.creation.jmock.ClassImposterizer.imposterise (ClassImposterizer.java:62) в орг .powermock.api.mockito.internal.moc kcreation.MockCreator.createMethodInvocationControl (MockCreator.java:111) на org.powermock.api.mockito.internal.mockcreation.MockCreator.mock (MockCreator.java:60) на org.powermock.api.mockito.PowerMockito. mockStatic (PowerMockito.java:70) на com.test.powermockstatics.TestStaticMockingWithoutPowerMockRunner.testStaticCall (TestStaticMockingWithoutPowerMockRunner.java:30) на sun.reflect.NativeMethodAccessorImpl.invoke0 (нативный метод) при sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43) по адресу java.lang.reflect.Method.invoke (Met hod.java:606) в org.junit.runners.model.FrameworkMethod $ 1.runReflectiveCall (FrameworkMethod.java:47) at org.junit.internal.runners.model.ReflectiveCallable.run (ReflectiveCallable.java:12) на org.junit.runners.model.FrameworkMethod.invokeExplosively (FrameworkMethod.java:44) на org.junit.internal.runners.statements.InvokeMethod.evaluate (InvokeMethod.java:17) в org.powermock .modules.junit4.rule.PowerMockStatement.evaluate (PowerMockRule.java:49) на org.junit.runners.ParentRunner.runLeaf (ParentRunner.java:271) в org.junit.runners.BlockJUnit4ClassRunner.runChild (BlockJUnit4ClassRunner.java : 70) по адресуorg.junit.runners.BlockJUnit4ClassRunner.runChild (BlockJUnit4ClassRunner.java:50) в org.junit.runners.ParentRunner $ 3.run (ParentRunner.java:238) в org.junit.runners.ParentRunner $ 1.schedule (ParentRunner .java: 63) на org.junit.runners.ParentRunner.runChildren (ParentRunner.java:236) на org.junit.runners.ParentRunner.access $ 000 (ParentRunner.java:53) в org.junit.runners.ParentRunner $ 2.оценить (ParentRunner.java:229) в org.junit.runners.ParentRunner.run (ParentRunner.java:309) по адресу org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run (JUnit4TestReference.java:50) на org.eclipse.jdt.internal.junit.runner.TestExecution.run (TestExecution.java:38) в org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests (RemoteTestRunner.java:467) на org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests (RemoteTestRunner.java:683) в org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run (RemoteTestRunner.java:390) на org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main (RemoteTestRunner.java:197)

Я выполняю рекомендации от Документов:

положить powermock- модуль-junit4 властвуй агента перед тем JUnit в классам

кто-нибудь знает официальное слово, если это ошибка в PowerMock или желаемое поведение (то есть, вы просто не можете издеваться с static методом на final класс с использованием PowerMockRule)?

EDIT:

Пожалуйста, смотрите уточняющие детали в the comments under Gábor Lipták's answer. Я делаю не хочу использовать статически загруженный Агент, так как появляется динамически загруженный Агент, который должен быть способен выполнить работу?

Я знаю, что начинающий агент статически будет работать. (К сожалению, это не вариант в моем проекте.) Значит, кто-нибудь знает, является ли сбой динамически загруженного агента ошибкой в ​​PowerMock? Или известное ограничение; и почему?

ответ

1

Для издевательских классов классов классов недостаточно. Вам нужен агент JVM.

Согласно docs:

В некоторых случаях (например, насмехаясь финальные классы) может потребоваться для нагрузки PowerMock агент усердия в Maven для того, чтобы тесты на работу в безошибочный. Если вы испытываете это, пожалуйста, добавьте следующее ваш pom.xml:

Нужен JVM аргумент издеваться финальные классы:

-javaagent:${settings.localRepository}/org/powermock/powermock-module-javaagent/1.5.6/powermock-module-javaagent-1.5.6.jar 
+0

Здесь нет Maven. –

+0

Затем загрузите банку и введите команду: java .... -javaagent: pathtojar/powermock-module-javaagent-1.5.6.jar. Это все. –

+0

Я согласен, мне нужен агент. Агенты могут быть добавлены динамически, если вы посмотрите на код в https://github.com/jayway/powermock/blob/master/modules/module-impl/agent/src/main/java/org/powermock/modules/agent /PowerMockAgent.java для метода initializeIfNeeded, вы увидите, что он динамически привязывает Агента к запущенному процессу JVM. Я, к сожалению, должен динамически загружать Агент и не могу добавить аргументы для статической загрузки агента при запуске JVM. Документы, однако, заставляют это звучать так (статическая загрузка агента) необходимо только для использования с Maven. –

15

Вы должны подготовить класс для тестирования!

@PrepareForTest(MyFinalClass.class)

+0

Это работало для меня – UpAllNight

+2

Зачем мне это делать? –

1

У меня был один и тот же симптом и может решить, расширив класс тест с PowerMockTestCase.

public class NetworkManagerUtilsTest extends PowerMockTestCase { 

Не уверен, что это решение применимо здесь.