test mock guia examples doubles datos java spring unit-testing mockito

java - guia - ¿Cómo puede Mockito capturar los monumentos pasados a los métodos de un objeto simulado inyectado?



mockito examples in java (2)

Estoy intentando probar una clase de servicio, que hace uso interno de un objeto de conexión Spring AMQP. Este objeto de conexión es inyectado por Spring. Sin embargo, no quiero que mi prueba de unidad se comunique realmente con el agente de AMQP, por lo que estoy usando Mockito inyectar un simulacro del objeto de conexión.

/** * The real service class being tested. Has an injected dependency. */ public class UserService { @Autowired private AmqpTemplate amqpTemplate; public final String doSomething(final String inputString) { final String requestId = UUID.randomUUID().toString(); final Message message = ...; amqpTemplate.send(requestId, message); return requestId; } } /** * Unit test */ public class UserServiceTest { /** This is the class whose real code I want to test */ @InjectMocks private UserService userService; /** This is a dependency of the real class, that I wish to override with a mock */ @Mock private AmqpTemplate amqpTemplateMock; @Before public void initMocks() { MockitoAnnotations.initMocks(this); } @Test public void testDoSomething() { doNothing().when(amqpTemplateMock).send(anyString(), any(Message.class)); // Call the real service class method, which internally will make // use of the mock (I''ve verified that this works right). userService.doSomething(...); // Okay, now I need to verify that UUID string returned by // "userService.doSomething(...) matches the argument that method // internally passed to "amqpTemplateMock.send(...)". Up here // at the unit test level, how can I capture the arguments passed // to that inject mock for comparison? // // Since the value being compared is a UUID string created // internally within "userService", I cannot just verify against // a fixed expected value. The UUID will by definition always be // unique. } }

Los comentarios en este ejemplo de código esperan que la pregunta sea clara. Cuando Mockito inyecta una dependencia simulada en una clase real, y las pruebas unitarias en la clase real hacen que se realicen llamadas a la simulación, ¿cómo puede recuperar posteriormente los argumentos exactos que se pasaron a la simulación inyectada?


Puede conectar doAnswer() al código auxiliar del método send() en amqpTemplateMock y luego capturar los argumentos de invocación de AmqpTemplate.send() .

Haz la primera línea de tu testDoSomething() be this

Mockito.doAnswer(new Answer<Void>() { @Override public Void answer(final InvocationOnMock invocation) { final Object[] args = invocation.getArguments(); System.out.println("UUID=" + args[0]); // do your assertions here return null; } }).when(amqpTemplateMock).send(Matchers.anyString(), Matchers.anyObject());

Poniendo todo junto, la prueba se convierte en

import org.junit.Before; import org.junit.Test; import org.mockito.InjectMocks; import org.mockito.Matchers; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; public class UserServiceTest { /** This is the class whose real code I want to test */ @InjectMocks private UserService userService; /** This is a dependency of the real class, that I wish to override with a mock */ @Mock private AmqpTemplate amqpTemplateMock; @Before public void initMocks() { MockitoAnnotations.initMocks(this); } @Test public void testDoSomething() throws Exception { Mockito.doAnswer(new Answer<Void>() { @Override public Void answer(final InvocationOnMock invocation) { final Object[] args = invocation.getArguments(); System.out.println("UUID=" + args[0]); // do your assertions here return null; } }).when(amqpTemplateMock).send(Matchers.anyString(), Matchers.anyObject()); userService.doSomething(Long.toString(System.currentTimeMillis())); } }

Esto da salida

UUID = 8e276a73-12fa-4a7e-a7cc-488d1ce0291f

Encontré esto leyendo este post, Cómo hacer que los métodos de simulacro a vacío con mockito


Utilice uno, o más, ArgumentCaptor s.

No está claro cuáles son sus tipos aquí, pero de todos modos. Supongamos que tienes un simulacro que tiene un método doSomething() tomando un Foo como argumento, luego haces esto:

final ArgumentCaptor<Foo> captor = ArgumentCaptor.forClass(Foo.class); verify(mock).doSomething(captor.capture()); final Foo argument = captor.getValue(); // Test the argument

Además, parece que tu método devuelve vacío y no quieres que haga nada. Solo escribe esto:

doNothing().when(theMock).doSomething(any());