ventanas ventana una pasar otro otra llamar formulario desde dentro crear conectar como boton abrir java junit mockito

java - ventana - Mockito: tratar de espiar el método es llamar al método original



crear una ventana dentro de otra ventana en java (7)

En mi caso, utilizando Mockito 2.0, tuve que cambiar todos los parámetros any () a nullable () para apagar la llamada real.

Estoy usando Mockito 1.9.0. Quiero simular el comportamiento de un solo método de una clase en una prueba JUnit, así que tengo

final MyClass myClassSpy = Mockito.spy(myInstance); Mockito.when(myClassSpy.method1()).thenReturn(myResults);

El problema es que, en la segunda línea, a myClassSpy.method1() realmente se le llama, lo que resulta en una excepción. La única razón por la que estoy usando simulacros es para que luego, cuando se myClassSpy.method1() se llamará al método real y se myResults objeto myResults .

MyClass es una interfaz y myInstance es una implementación de eso, si eso importa.

¿Qué necesito hacer para corregir este comportamiento de espionaje?


He encontrado otra razón para que el espía llame al método original.

Alguien tuvo la idea de burlarse de una clase final , y descubrió acerca de MockMaker :

Como esto funciona de manera diferente a nuestro mecanismo actual y este tiene limitaciones diferentes y como queremos recopilar experiencia y comentarios de los usuarios, esta función tenía que activarse explícitamente para estar disponible; se puede hacer a través del mecanismo de extensión mockito creando el archivo src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker contiene una sola línea: mock-maker-inline

Fuente: https://github.com/mockito/mockito/wiki/What%27s-new-in-Mockito-2#mock-the-unmockable-opt-in-mocking-of-final-classesmethods

Después de fusionar y traer ese archivo a mi máquina, mis pruebas fallaron.

Solo tuve que eliminar la línea (o el archivo) y spy() funcionó.


Mi caso fue diferente de la respuesta aceptada. Estaba intentando burlar un método de paquete privado para una instancia que no vivía en ese paquete

package common; public class Animal { void packageProtected(); } package instances; class Dog extends Animal { }

y las clases de prueba

package common; public abstract class AnimalTest<T extends Animal> { @Before setup(){ doNothing().when(getInstance()).packageProtected(); } abstract T getInstance(); } package instances; class DogTest extends AnimalTest<Dog> { Dog getInstance(){ return spy(new Dog()); } @Test public void myTest(){} }

La compilación es correcta, pero cuando intenta configurar la prueba, invoca el método real en su lugar.

Declarar el método protegido o resolver el problema públicamente , aunque no es una solución limpia.


Otro escenario posible que puede causar problemas con los espías es cuando está probando frijoles de primavera (con el marco de prueba de primavera) o algún otro marco que esté procesando sus objetos durante la prueba .

Ejemplo

@Autowired private MonitoringDocumentsRepository repository void test(){ repository = Mockito.spy(repository) Mockito.doReturn(docs1, docs2) .when(repository).findMonitoringDocuments(Mockito.nullable(MonitoringDocumentSearchRequest.class)); }

En el código anterior, tanto Spring como Mockito intentarán usar su objeto MonitoringDocumentsRepository, pero Spring será el primero, lo que provocará la llamada real del método findMonitoringDocuments. Si depuramos nuestro código justo después de colocar un objeto espía en el repositorio, se verá así dentro del depurador:

repository = MonitoringDocumentsRepository$$EnhancerBySpringCGLIB$$MockitoMock$

@SpyBean al rescate

Si, en @Autowired anotación @Autowired @SpyBean anotación @SpyBean , resolveremos el problema anterior, la anotación SpyBean también inyectará un objeto de repositorio, pero primero será procesado por Mockito y se verá así dentro del depurador

repository = MonitoringDocumentsRepository$$MockitoMock$$EnhancerBySpringCGLIB$

Y aquí está el código:

@SpyBean private MonitoringDocumentsRepository repository void test(){ Mockito.doReturn(docs1, docs2) .when(repository).findMonitoringDocuments(Mockito.nullable(MonitoringDocumentSearchRequest.class)); }


Permítanme citar la documentación oficial :

Importante gotcha en espiar objetos reales!

A veces es imposible usar cuando (Objeto) para espiar a espías. Ejemplo:

List list = new LinkedList(); List spy = spy(list); // Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty) when(spy.get(0)).thenReturn("foo"); // You have to use doReturn() for stubbing doReturn("foo").when(spy).get(0);

En tu caso va algo como:

doReturn(resulstIWant).when(myClassSpy).method1();


Una forma de asegurarse de que no se llame a un método de una clase es anular el método con un dummy.

WebFormCreatorActivity activity = spy(new WebFormCreatorActivity(clientFactory) {//spy(new WebFormCreatorActivity(clientFactory)); @Override public void select(TreeItem i) { log.debug("SELECT"); }; });


¡La respuesta de Tomasz Nurkiewicz parece no contar toda la historia!

NB versión de Mockito: 1.10.19.

Soy muy nuevo en Mockito, así que no puedo explicar el siguiente comportamiento: si hay un experto que pueda mejorar esta respuesta, siéntase libre.

El método en cuestión aquí, getContentStringValue , NO es final y NO static .

Esta línea llama al método original getContentStringValue :

doReturn( "dummy" ).when( im ).getContentStringValue( anyInt(), isA( ScoreDoc.class ));

Esta línea no llama al método original getContentStringValue :

doReturn( "dummy" ).when( im ).getContentStringValue( anyInt(), any( ScoreDoc.class ));

Por razones que no puedo responder, el uso de isA() hace que el comportamiento previsto (?) "No llamar al método" de doReturn falle.

Veamos las firmas de métodos involucradas aquí: ambos son métodos static de Matchers . El Javadoc dice que ambos devuelven el null , lo cual es un poco difícil de entender en sí mismo. Presumiblemente, el objeto de Class pasado como parámetro se examina, pero el resultado nunca se calcula o se descarta. Dado que null puede significar cualquier clase y que espera que no se llame al método isA( ... ) , no podrían las firmas de isA( ... ) y any( ... ) simplemente devolver null lugar de un parámetro genérico * <T> ?

De todas formas:

public static <T> T isA(java.lang.Class<T> clazz) public static <T> T any(java.lang.Class<T> clazz)

La documentación de la API no da ninguna pista sobre esto. También parece decir que la necesidad de tal comportamiento de "no llamar método" es "muy rara". Personalmente uso esta técnica todo el tiempo : por lo general, me parece que la burla involucra algunas líneas que "configuran la escena" ... seguidas de un método que luego "reproduce" la escena en el contexto simulado en el que has organizado ... . y mientras configuras el escenario y los accesorios, lo último que quieres es que los actores entren en el escenario a la izquierda y comiencen a mostrar sus corazones ...

Pero esto va más allá de mi grado de pago ... Invito explicaciones de cualquier sumo sacerdote de Mockito que pase ...

* ¿Es "parámetro genérico" el término correcto?