[java] 조롱 된 메소드가 전달 된 인수를 반환하게하십시오.

다음과 같은 메소드 서명을 고려하십시오.

public String myFunction(String abc);

Mockito가 메소드가 수신 한 것과 동일한 문자열을 리턴하도록 도울 수 있습니까?



답변

Mockito에서 답변을 만들 수 있습니다. myFunction 메소드가있는 Application이라는 인터페이스가 있다고 가정 해 봅시다.

public interface Application {
  public String myFunction(String abc);
}

Mockito 답변이있는 테스트 방법은 다음과 같습니다.

public void testMyFunction() throws Exception {
  Application mock = mock(Application.class);
  when(mock.myFunction(anyString())).thenAnswer(new Answer<String>() {
    @Override
    public String answer(InvocationOnMock invocation) throws Throwable {
      Object[] args = invocation.getArguments();
      return (String) args[0];
    }
  });

  assertEquals("someString",mock.myFunction("someString"));
  assertEquals("anotherString",mock.myFunction("anotherString"));
}

Mockito 1.9.5 및 Java 8부터 람다 식을 사용할 수도 있습니다.

when(myMock.myFunction(anyString())).thenAnswer(i -> i.getArguments()[0]);


답변

Mockito 1.9.5 이상을 사용하는 경우 Answer객체를 만들 수있는 새로운 정적 메서드가 있습니다 . 당신은 뭔가를 작성해야합니다

import static org.mockito.Mockito.when;
import static org.mockito.AdditionalAnswers.returnsFirstArg;

when(myMock.myFunction(anyString())).then(returnsFirstArg());

또는 대안 적으로

doAnswer(returnsFirstArg()).when(myMock).myFunction(anyString());

returnsFirstArg()메소드는 AdditionalAnswers클래스 에서 정적이며 Mockito 1.9.5에 새로 도입되었습니다. 올바른 정적 가져 오기가 필요합니다.


답변

Java 8을 사용하면 이전 버전의 Mockito에서도 한 줄 답변을 만들 수 있습니다.

when(myMock.myFunction(anyString()).then(i -> i.getArgumentAt(0, String.class));

물론 이것은 AdditionalAnswersDavid Wallace가 제안한 것만 큼 ​​유용 하지는 않지만 “즉시”인수를 변환하려는 경우 유용 할 수 있습니다.


답변

나는 비슷한 문제가 있었다. 목표는 객체를 유지하고 이름으로 반환 할 수있는 서비스를 조롱하는 것이 었습니다. 서비스는 다음과 같습니다.

public class RoomService {
    public Room findByName(String roomName) {...}
    public void persist(Room room) {...}
}

서비스 모의는 맵을 사용하여 Room 인스턴스를 저장합니다.

RoomService roomService = mock(RoomService.class);
final Map<String, Room> roomMap = new HashMap<String, Room>();

// mock for method persist
doAnswer(new Answer<Void>() {
    @Override
    public Void answer(InvocationOnMock invocation) throws Throwable {
        Object[] arguments = invocation.getArguments();
        if (arguments != null && arguments.length > 0 && arguments[0] != null) {
            Room room = (Room) arguments[0];
            roomMap.put(room.getName(), room);
        }
        return null;
    }
}).when(roomService).persist(any(Room.class));

// mock for method findByName
when(roomService.findByName(anyString())).thenAnswer(new Answer<Room>() {
    @Override
    public Room answer(InvocationOnMock invocation) throws Throwable {
        Object[] arguments = invocation.getArguments();
        if (arguments != null && arguments.length > 0 && arguments[0] != null) {
            String key = (String) arguments[0];
            if (roomMap.containsKey(key)) {
                return roomMap.get(key);
            }
        }
        return null;
    }
});

이제이 모의에서 테스트를 실행할 수 있습니다. 예를 들면 다음과 같습니다.

String name = "room";
Room room = new Room(name);
roomService.persist(room);
assertThat(roomService.findByName(name), equalTo(room));
assertNull(roomService.findByName("none"));


답변

Java 8을 사용하면 Steve의 대답 이 될 수 있습니다.

public void testMyFunction() throws Exception {
    Application mock = mock(Application.class);
    when(mock.myFunction(anyString())).thenAnswer(
    invocation -> {
        Object[] args = invocation.getArguments();
        return args[0];
    });

    assertEquals("someString", mock.myFunction("someString"));
    assertEquals("anotherString", mock.myFunction("anotherString"));
}

편집 : 더 짧음 :

public void testMyFunction() throws Exception {
    Application mock = mock(Application.class);
    when(mock.myFunction(anyString())).thenAnswer(
        invocation -> invocation.getArgument(0));

    assertEquals("someString", mock.myFunction("someString"));
    assertEquals("anotherString", mock.myFunction("anotherString"));
}


답변

이것은 꽤 오래된 질문이지만 여전히 관련이 있다고 생각합니다. 또한 허용되는 답변은 문자열에만 적용됩니다. 한편 Mockito 2.1이 있으며 일부 수입품이 변경되었으므로 현재 답변을 공유하고 싶습니다.

import static org.mockito.AdditionalAnswers.returnsFirstArg;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;

@Mock
private MyClass myClass;

// this will return anything you pass, but it's pretty unrealistic
when(myClass.myFunction(any())).then(returnsFirstArg());
// it is more "life-like" to accept only the right type
when(myClass.myFunction(any(ClassOfArgument.class))).then(returnsFirstArg());

myClass.myFunction은 다음과 같습니다.

public class MyClass {
    public ClassOfArgument myFunction(ClassOfArgument argument){
        return argument;
    }
}


답변

나는 비슷한 것을 사용한다 (기본적으로 같은 접근법이다). 때로는 특정 입력에 대해 모의 객체가 미리 정의 된 출력을 반환하도록하는 것이 유용합니다. 이것은 다음과 같습니다.

private Hashtable<InputObject,  OutputObject> table = new Hashtable<InputObject, OutputObject>();
table.put(input1, ouput1);
table.put(input2, ouput2);

...

when(mockObject.method(any(InputObject.class))).thenAnswer(
       new Answer<OutputObject>()
       {
           @Override
           public OutputObject answer(final InvocationOnMock invocation) throws Throwable
           {
               InputObject input = (InputObject) invocation.getArguments()[0];
               if (table.containsKey(input))
               {
                   return table.get(input);
               }
               else
               {
                   return null; // alternatively, you could throw an exception
               }
           }
       }
       );