2009-12-30 18 views
10

Estamos escribiendo pruebas JUnit para una clase que utiliza el autovínculo de Spring para inyectar una dependencia que es una instancia de una interfaz. Como la clase bajo prueba nunca instancia explícitamente la dependencia o la ha pasado en un constructor, parece que JMockit tampoco se siente obligado a crear una instancia.Uso de JMockit para simular implementaciones de interfaz autocableadas

Hasta ahora hemos estado usando SpringRunner para tener Spring load mock depencies para nosotros, que funciona. Dos cosas que no nos gustan de esto son 1) el marco Spring debe cargarse e inicializarse cada vez que se ejecutan las pruebas, lo que no es exactamente rápido, y 2) estamos obligados a crear explícitamente todas las dependencias simuladas como clases reales, algo que JMockit ayuda a eliminar.

Aquí está un ejemplo simplificado de lo que estamos probando:

public class UnitUnderTest { 

    @Autowired 
    ISomeInterface someInterface; 

    public void callInterfaceMethod() { 

     System.out.println("UnitUnderTest.callInterfaceMethod calling someInterface.doSomething"); 
     someInterface.doSomething(); 
    } 

} 

Entonces, la pregunta es, ¿hay una manera de tener JMockit crear una maqueta someInterface?

+0

ver también: http://stackoverflow.com/questions/1638911/mock-object-and-spring-annotations –

Respuesta

10

JMockit siempre será una instancia de una interfaz burlado (excepto en el caso de un campo maqueta final), pero que sólo se produce en el código de prueba. No inyectará automáticamente la instancia en el código bajo prueba.

Tendría que inyectar manualmente la instancia de simulacro. Por ejemplo:

public class SomeTest 
{ 
    @Autowired UnitUnderTest unitUnderTest; 
    @Mocked ISomeInterface theMock; // created and assigned automatically 

    @Test 
    public void testSomeMethod() 
    { 
     Deencapsulation.setField(unitUnderTest, theMock); 
     //proceed with unit test here 
    } 
} 

mockit.Deencapsulation es una clase de utilidad basada en la reflexión que le permite invocar métodos privados, obtener campos/sistema, etc.

+4

Solo una nota: desde que se publicó esta respuesta, JMockit ha agregado soporte para la inyección automática de objetos falsos en clases probadas. En este ejemplo, reemplace '@ Autowired' con' @ Tested' y '@ Mocked' con' @ Injectable'. –

+0

¡Wow @ Rogério! ¡eso es bueno! JMockit es tan poderoso ... ¡Me encanta! –

+0

@ Rogério ¿Puede la herramienta de cobertura jmockit generar un informe para mockito? nuestro código de prueba heredado es con mockito. Cualquier enlace es útil. – yuyue007

8

Puede usar org.springframework.test.util.ReflectionTestUtils para inyectar explícitamente su ISomeInterface burlado en su caso de prueba.

Ver documentation

+1

(+1) esa es una buena clase que no sabía :) – Bozho

+0

Me encanta encontrar estos pequeñas gemas en Spring API ... +1 – skaffman

+0

Esta es una clase útil para estar seguro. Aún así, tener que crear explícitamente las derrotas simuladas es una de las principales razones para usar JMockit en primer lugar. – SwimsZoots

4

Con los consejos amablemente proporcionados anteriormente, esto es lo que me pareció más útil como alguien muy nuevo en JMockit: JMockit proporciona la clase Deencapsulation para permitirle establecer los valores de los campos dependientes privados (no es necesario arrastrar las bibliotecas Spring), y la clase MockUp que le permite crear explícitamente una implementación de una interfaz y simulacro uno o más métodos de la interfaz. He aquí cómo terminé resolviendo este caso particular:

@Before 
public void setUp() { 

    IMarketMakerDal theMock = new MockUp <IMarketMakerDal>() { 

     @Mock 
     MarketMakerDcl findByMarketMakerGuid(String marketMakerGuid) { 

     MarketMakerDcl marketMakerDcl = new MarketMakerDcl(); 
     marketMakerDcl.setBaseCurrencyCode(CURRENCY_CODE_US_DOLLAR); 
     return marketMakerDcl; 
     } 
    }.getMockInstance(); 

    setField(unitUnderTest, theMock); 
} 

Gracias a todos por la ayuda.

2

Para aquellas personas que se reunieron

java.lang.IllegalStateException: Missing @Injectable for field *** 

o

error
java.lang.IllegalStateException: Missing @Tested class for field *** 

cuando se utiliza jmockit burlarse @autowired campo en spring (o) marco, lo hice por debajo de dos pasos para evitar por encima de errores:

  1. use @Tested(fullyInitialized=true) lugar de @Tested

https://groups.google.com/forum/#!msg/jmockit-users/uo0S51lSX24/lQhLNN--eJcJ

  1. revertir la versión de jmockit de nuevo a 1.18 o los anteriores

https://groups.google.com/forum/#!topic/jmockit-users/wMFZggsA8LM

0

Si tiene una anotación @Qualifier para la interfaz, debe nombrar su campo @Injectable exactamente como se nombra en el calificador.

Aquí es cita de JMockit doc: nombres

personalizado especificado en las anotaciones de campo de Java EE (@Resource (nombre), @Named) o en el marco de la primavera (@Qualifier) ​​se utilizan cuando se busca una coincidencia @Injectable o @Tested value. Cuando tal nombre contiene un - (guión) o. (punto), se usa el nombre correspondiente de camello.

Por ejemplo:

@Component 
public class AClass { 

    @Autowired 
    private Bean1 bean1; 

    @Autowired 
    @Qualifier("my-dashed-name") 
    private AmqpTemplate rpcTemplate; 
} 

clase de prueba Unidad:

public class AClassTest { 

    @Injectable 
    private Bean1 bean1; 

    @Injectable 
    private AmqpTemplate myDashedName; 

    @Tested 
    private AClass aClass = new AClass(); 
} 

Además, no hay necesidad de utilizar setFiled para cada bean @Autowired, todos los campos inyecta automáticamente cuando la clase @Tested instancia . Probado en JMockit ver. 1.30

Cuestiones relacionadas