¿Cómo me burlo de los métodos estáticos en una clase con easymock?

Supongamos que tengo una clase así:

public class StaticDude{ public static Object getGroove() { // ... some complex logic which returns an object }; } 

¿Cómo me burlo de la llamada al método estático usando easy mock? StaticDude.getGroove() .

Estoy usando easy mock 3.0

No estoy seguro de cómo usar EasyMock puro, pero considere usar las extensiones PowerMock para EasyMock.

Tiene muchas funciones geniales para hacer justo lo que necesita: https://github.com/jayway/powermock/wiki/MockStatic

Easymock es un marco de prueba para “interfaces (y objetos a través de la extensión de clase)” para que pueda simular una clase sin una interfaz. Considere crear un objeto interconectado con un accesorio para su clase estática y luego simular ese acessor.

EDITAR: Por cierto, no recomendaría hacer clases estáticas. Es mejor tener todo interconectado si estás haciendo TDD.

Solo en caso de que PowerMock no esté disponible por alguna razón:

Puede mover la llamada estática a un método, anular este método en la creación de instancias de la clase probada en la clase de prueba, crear una interfaz local en la clase de prueba y usar su método en el método de superposición:

 private interface IMocker { boolean doSomething(); } IMocker imocker = EasyMock.createMock(IMocker.class); ... @Override void doSomething() { imocker.doSomething(); } ... EasyMock.expect(imocker.doSomething()).andReturn(true); 

En términos generales, no es posible burlarse de un método estático sin utilizar algún tipo de acceso, lo que parece frustrar el propósito de usar un método estático. Puede ser bastante frustrante.

Hay una herramienta que conozco llamada “TypeMock Isolator” que usa algún tipo de Magia Satánica para burlarse de los métodos estáticos, pero esa herramienta es bastante costosa.

El problema es que no conozco ninguna forma de anular un método estático. No puedes declararlo virtual. no puedes incluirlo en una interfaz.

Perdón por ser un nelly negativo.

Agregando un ejemplo sobre cómo implementar la simulación estática a lo largo de simulacros regulares de clases inyectadas con EasyMock / PowerMock, ya que el ejemplo vinculado solo muestra la simulación estática.

Y con PowerMockRunner los servicios de @Mock no están conectados en el servicio @TestSubject para probar.

Digamos que tenemos un servicio que queremos probar, ServiceOne:

 import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class ServiceOne { @Autowired private ServiceTwo serviceTwo; public String methodToTest() { String returnServ2 = serviceTwo.methodToMock(); return ServiceUtils.addPlus(returnServ2); } } 

Lo cual llama a otro servicio que querremos burlar, ServiceTwo:

 import org.springframework.stereotype.Service; @Service public class ServiceTwo { public String methodToMock() { return "ServiceTwoReturn"; } } 

Y que llama a un método estático de clase final, ServiceUtils:

 public final class ServiceUtils { public static String addPlus(String pParam) { return "+" + pParam; } } 

Al llamar a ServiceOne.methodToTest() obtenemos "+ServiceTwoReturn" como devolución.


Junit Test con EasyMock, burlándose solo del servicio inyectado ServiceTwo Spring:

 import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; import static org.junit.Assert.assertEquals; import org.easymock.EasyMockRunner; import org.easymock.Mock; import org.easymock.TestSubject; import org.junit.Test; import org.junit.runner.RunWith; @RunWith(EasyMockRunner.class) public class ExempleTest { @TestSubject private ServiceOne serviceToTest = new ServiceOne(); @Mock private ServiceTwo serviceMocked; @Test public void testMethodToTest() { String mockedReturn = "return2"; expect(serviceMocked.methodToMock()).andReturn(mockedReturn); replay(serviceMocked); String result = serviceToTest.methodToTest(); verify(serviceMocked); assertEquals("+" + mockedReturn, result); } } 

Junit Test con EasyMock y PowerMock, burlando el servicio inyectado de ServiceTwo Spring pero también la clase final y su método estático:

 import static org.easymock.EasyMock.expect; import static org.junit.Assert.assertEquals; import static org.powermock.api.easymock.PowerMock.createMock; import static org.powermock.api.easymock.PowerMock.mockStatic; import static org.powermock.reflect.Whitebox.setInternalState; import org.easymock.Mock; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.api.easymock.PowerMock; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @RunWith(PowerMockRunner.class) @PrepareForTest(ServiceUtils.class) public class ExempleTest { private ServiceOne serviceToTest; private ServiceTwo serviceMocked; @Before public void setUp() { serviceToTest = new ServiceOne(); serviceMocked = createMock(ServiceTwo.class); // This will wire the serviced mocked into the service to test setInternalState(serviceToTest, serviceMocked); mockStatic(ServiceUtils.class); } @Test public void testMethodToTest() { String mockedReturn = "return2"; String mockedStaticReturn = "returnStatic"; expect(serviceMocked.methodToMock()).andReturn(mockedReturn); expect(ServiceUtils.addPlus(mockedReturn)).andReturn(mockedStaticReturn); PowerMock.replayAll(); String result = serviceToTest.methodToTest(); PowerMock.verifyAll(); assertEquals(mockedStaticReturn, result); } } 
    Intereting Posts