복붙노트

[SPRING] 어떻게 Mockito가 주입 된 모의 객체의 메소드에 전달 된 인수를 캡처 할 수 있습니까?

SPRING

어떻게 Mockito가 주입 된 모의 객체의 메소드에 전달 된 인수를 캡처 할 수 있습니까?

내부적으로 Spring AMQP 연결 객체를 사용하는 서비스 클래스를 테스트하려고한다. 이 연결 개체는 Spring에 의해 주입된다. 그러나, 나는 AMQP 중개인과 실제로 통신하기 위해 유닛 테스트를 원하지 않기 때문에 Mockito를 사용하여 연결 객체의 모의 (mock)를 주입한다.

/** 
 * 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.
   }
}

이 코드 샘플의 주석은 질문을 명확하게 제시합니다. Mockito가 실제 클래스에 모의 의존성을 주입하고 실제 클래스의 유닛 테스트가 모의 객체를 호출하게 만들 때, 나중에 어떻게 주입 된 모의 객체에 전달 된 정확한 인수를 검색 할 수 있습니까?

해결법

  1. ==============================

    1.하나 이상의 ArgumentCaptors를 사용하십시오.

    하나 이상의 ArgumentCaptors를 사용하십시오.

    어쨌든 귀하의 유형이 여기에 어떤 것인지 명확하지 않습니다. doSomething () 메소드가 Foo를 인자로 취하는 모의 객체를 가지고 있다고 가정 해 보겠습니다.

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

    또한 메서드가 void를 반환하고 아무 것도하지 않기를 바랍니다. 다음과 같이 작성하십시오.

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

    2.amqpTemplateMock에서 doAnswer ()를 send () 메서드의 스텁에 연결 한 다음 AmqpTemplate.send ()의 호출 인수를 캡처 할 수 있습니다.

    amqpTemplateMock에서 doAnswer ()를 send () 메서드의 스텁에 연결 한 다음 AmqpTemplate.send ()의 호출 인수를 캡처 할 수 있습니다.

    testDoSomething ()의 첫 번째 행을 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());
    

    모든 것을 합치면 테스트가됩니다.

    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()));
      }
    }
    

    이것은 결과를 준다.

    나는이 지위를 읽음으로써 이것을 발견했다. mockito를 사용하여 void 메소드에 모의 만드는 법

  3. from https://stackoverflow.com/questions/29169759/how-can-mockito-capture-arguments-passed-to-an-injected-mock-objects-methods by cc-by-sa and MIT license