¿Es posible burlarse de un método estático en una clase final usando una PowerMockRule en lugar de la PowerMockRunner?

De acuerdo alos documentos de PowerMock, Debería poder ejecutar usando unPowerMockRule en lugar de@RunWith(PowerMockRunner.class) y obtener los mismos resultados.

Parece que encontré un caso en el que esto no es cierto.

La siguiente muestra funciona bien:

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);
  }
}

Pero cuando se cambia a una regla así:

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);
  }
}

Me sale la siguiente excepción:

java.lang.IllegalArgumentException: no se puede subclasificar la clase final clase com.test.powermockstatics.FinalClassWithStaticCall en org.mockito.cglib.proxy.Enhancer.generateClass (Enhancer.java:447) en org.mockito.cglib.core.DefaultGeneratorStrategyegeneratorStrategyegenerador DefaultGeneratorStrategy.java:25) en org.mockito.cglib.core.AbstractClassGenerator.create (AbstractClassGenerator.java:217) en org.mockito.cglib.proxy.Enhancer.createHelper (Enhancer.java:378) en org.mockito.org .proxy.Enhancer.createClass (Enhancer.java:318) en org.mockito.internal.creation.jmock.ClassImposterizer.createProxyClass (ClassImposterizer.java:110) en org.mockito.internal.creation.jmock.ClassImposterizer.imposterise (Class) .java: 62) en org.powermock.api.mockito.internal.mockcreation.MockCreator.createMethodInvocationControl (MockCreator.java:111) en org.powermock.api.mockito.internal.mockcreation.MockCreator.mock (MockCreator.jack: ) en org.powermock.api.mockito.PowerMockito.mockStatic (PowerMockito.java:70) en com.test.pow ermockstatics.TestStaticMockingWithoutPowerMockRunner.testStaticCall (TestStaticMockingWithoutPowerMockRunner.java:30) en sun.reflect.NativeMethodAccessorImpl.invoke0 (Método Nativo) en sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:57) en sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl. java: 43) en java.lang.reflect.Method.invoke (Method.java:606) en org.junit.runners.model.FrameworkMethod $ 1.runReflectiveCall (FrameworkMethod.java:47) en org.junit.internal.runners. model.ReflectiveCallable.run (ReflectiveCallable.java:12) en org.junit.runners.model.FrameworkMethod.invokeExplosively (FrameworkMethod.java:44) en org.junit.internal.runners.statements.InvokeMethod.evaluate (InvokeMethod.java: 17) en org.powermock.modules.junit4.rule.PowerMockStatement.evaluate (PowerMockRule.java:49) en org.junit.runners.ParentRunner.runLeaf (ParentRunner.java:271) en org.junit.runners.BlockJUnner.ClassRununr4 (BlockJUnit4ClassRunner.java:70) en org.junit. runners.BlockJUnit4ClassRunner.runChild (BlockJUnit4ClassRunner.java:50) en org.junit.runners.ParentRunner $ 3.run (ParentRunner.java:238) en org.junit.runners.ParentRunner $ 1.schedu.org (ParentRunner.org: Parent) .junit.runners.ParentRunner.runChildren (ParentRunner.java:236) en org.junit.runners.ParentRunner.access $ 000 (ParentRunner.java:53) en org.junit.runners.ParentRunner $ 2.evaluate (ParentRunner.java: ParentRunner.java: ParentRunner.java ) en org.junit.runners.ParentRunner.run (ParentRunner.java:309) en org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run (JUnit4TestReference.java:50) en org.eclipse.jdt.internal. junit.runner.TestExecution.run (TestExecution.java:38) en org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests (RemoteTestRunner.java:467) en org.eclipse.jdt.internal.junit.runner. RemoteTestRunner.runTests (RemoteTestRunner.java:683) en org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run (RemoteTestRunner.java:390) en org.eclipse.jdt.internal.junit.runner.unm. RemoteTestRunner .java: 197)

Estoy siguiendo la recomendación de los documentos para:

poner powermock-module-junit4-rule-agent antes de junit en el classpath

¿Alguien sabe la palabra oficial si esto es un error en PowerMock o el comportamiento deseado (es decir, simplemente no puede burlarse de unstatic método en unfinal clase usando unPowerMockRule)?

EDITAR:

Consulte los detalles aclaratorios enlos comentarios bajo la respuesta de Gábor Lipták. hagono ¿Desea utilizar un agente con carga estática, ya que parece que el agente con carga dinámica debería ser capaz de hacer el trabajo?

Sé que comenzar el agente estáticamente funcionará. (Desafortunadamente, esta no es una opción en mi proyecto). Entonces, ¿alguien sabe si la falla del Agente cargado dinámicamente es un error en PowerMock? O una limitación conocida; ¿y por qué?

Respuestas a la pregunta(3)

Su respuesta a la pregunta