¿Cómo me burlo de un método estático que devuelve void con PowerMock?


Tengo algunos métodos util estáticos en mi proyecto, algunos de ellos simplemente pasan o lanzan una excepción. Hay muchos ejemplos por ahí sobre cómo burlarse de un método estático que tiene un tipo de retorno que no sea void. Pero, ¿cómo puedo burlarme de un método estático que devuelve void a solo "doNothing()"?

La versión no vacía utiliza estas líneas de códigos:

@PrepareForTest(StaticResource.class)

...

PowerMockito.mockStatic(StaticResource.class);

...

Mockito.when(StaticResource.getResource("string")).thenReturn("string");

Sin embargo, si se aplica a un StaticResources que devuelve void, la compilación se quejará de que when(T) no es aplicable para nulo...

¿Alguna idea?

Una solución sería probablemente hacer que todos los métodos estáticos devuelvan algunos Boolean para tener éxito, pero no me gustan las soluciones.

Author: ROMANIA_engineer, 2012-03-06

4 answers

Puede hacerlo de la misma manera que lo hace con Mockito en instancias reales. Por ejemplo puedes encadenar stubs, la siguiente línea hará que la primera llamada no haga nada, luego la segunda y futura llamada a getResources lanzará la excepción:

// the stub of the static method
doNothing().doThrow(Exception.class).when(StaticResource.class);
StaticResource.getResource("string");

// the use of the mocked static code
StaticResource.getResource("string"); // do nothing
StaticResource.getResource("string"); // throw Exception

Gracias a un comentario de Matt Lachman, tenga en cuenta que si la respuesta predeterminada no se cambia en el tiempo de creación de la simulación, la simulación no hará nada por defecto. Por lo tanto, escribir el siguiente código equivale a no escribirlo.

doNothing().doThrow(Exception.class).when(StaticResource.class);
StaticResource.getResource("string");

Aunque ese ser dicho esto, puede ser interesante para los colegas que leerán la prueba que no espera nada para este código en particular. Por supuesto, esto se puede adaptar dependiendo de cómo se percibe comprensibilidad de la prueba.


Por cierto, en mi humilde opinión, debes evitar burlarte del código estático si estás creando un nuevo código. En Mockito creemos que generalmente es una pista de mal diseño, podría conducir a un código mal mantenible. Aunque el código heredado existente es otro historia.

En términos generales, si necesita simular un método privado o estático, este método hace demasiado y debe externalizarse en un objeto que se inyectará en el objeto probado.

Espero que eso ayude.

Saludos

 29
Author: Brice,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-16 07:11:57

Puedes stub un método vacío estático como este:

PowerMockito.doNothing().when(StaticResource.class, "getResource", anyString());

Aunque no estoy seguro de por qué te molestarías, porque cuando llamas a mockStatic(StaticResource.class) todos los métodos estáticos en StaticResource son por defecto stubbed

Más útil, puede capturar el valor pasado a StaticResource.getResource () así:

ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
PowerMockito.doNothing().when(
               StaticResource.class, "getResource", captor.capture());

Luego puede evaluar la cadena que se pasó a StaticResource.getResource así:

String resourceName = captor.getValue();
 64
Author: Justin Rowe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-02 08:16:48

En términos más simples, Imagínate si quieres simular debajo de la línea:

StaticClass.method();

Luego escribes debajo de las líneas de código para burlarte:

PowerMockito.mockStatic(StaticClass.class);
PowerMockito.doNothing().when(StaticClass.class);
StaticClass.method();
 11
Author: Vivek HJ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-04 12:30:54

Para simular un método estático que devuelve void para, por ejemplo, Fileutils.forceMKdir(File file),

Código de ejemplo:

File file =PowerMockito.mock(File.class);
PowerMockito.doNothing().when(FileUtils.class,"forceMkdir",file);
 3
Author: Oshin Talreja,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-07 06:11:45