다음과 같은 메소드 서명을 고려하십시오.
public String myFunction(String abc);
Mockito가 메소드가 수신 한 것과 동일한 문자열을 리턴하도록 도울 수 있습니까?
다음과 같은 메소드 서명을 고려하십시오.
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]);
when(...).then(Return.firstParameter())
when(foo(any()).then(i -> i.getArgumentAt(0, Bar.class))
. 또한 메소드 참조를 사용하고 실제 메소드를 호출 할 수 있습니다.
Iterator<? extends ClassName>
하면 thenReturn()
명령문 에서 모든 종류의 캐스트 문제를 일으키는 반환 방법으로 문제를 해결할 수 있습니다.
when(foo(any()).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에 새로 도입되었습니다. 올바른 정적 가져 오기가 필요합니다.
when(...).then(returnsFirstArg())
실수로 when(...).thenReturn(returnsFirstArg())
줬습니다java.lang.ClassCastException: org.mockito.internal.stubbing.answers.ReturnsArgumentAt cannot be cast to
static org.mockito.AdditionalAnswers.returnsFirstArg
. 이것은 returnsFirstArg를 사용합니다. 또한, when(myMock.myFunction(any())).then(returnsFirstArg())
Mockito 2.20에서 가능합니다. *
Java 8을 사용하면 이전 버전의 Mockito에서도 한 줄 답변을 만들 수 있습니다.
when(myMock.myFunction(anyString()).then(i -> i.getArgumentAt(0, String.class));
물론 이것은 AdditionalAnswers
David Wallace가 제안한 것만 큼 유용 하지는 않지만 "즉시"인수를 변환하려는 경우 유용 할 수 있습니다.
long
여전히 권투와 함께 작동 Long.class
합니까?
나는 비슷한 문제가 있었다. 목표는 객체를 유지하고 이름으로 반환 할 수있는 서비스를 조롱하는 것이 었습니다. 서비스는 다음과 같습니다.
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
}
}
}
);
ArgumentCaptor와 함께 verify ()를 사용하여 테스트에서 실행을 보장하고 ArgumentCaptor를 사용하여 인수를 평가할 수 있습니다.
ArgumentCaptor<String> argument = ArgumentCaptor.forClass(String.class);
verify(mock).myFunction(argument.capture());
assertEquals("the expected value here", argument.getValue());
인수의 값은 argument.getValue ()를 통해 추가 조작 / 확인 / 무엇이든 액세스 할 수 있습니다.
이것은 조금 낡았지만 같은 문제가 있었기 때문에 여기에 왔습니다. JUnit을 사용하고 있지만 이번에는 mockk이있는 Kotlin 앱에서 사용합니다. Java 대응과 참조 및 비교하기 위해 여기에 샘플을 게시하고 있습니다.
@Test
fun demo() {
// mock a sample function
val aMock: (String) -> (String) = mockk()
// make it return the same as the argument on every invocation
every {
aMock.invoke(any())
} answers {
firstArg()
}
// test it
assertEquals("senko", aMock.invoke("senko"))
assertEquals("senko1", aMock.invoke("senko1"))
assertNotEquals("not a senko", aMock.invoke("senko"))
}
ArgumentCaptor 를 사용하여이를 달성 할 수 있습니다.
빈 함수가 그렇게 있다고 상상해보십시오.
public interface Application {
public String myFunction(String abc);
}
그런 다음 테스트 수업에서
//Use ArgumentCaptor to capture the value
ArgumentCaptor<String> param = ArgumentCaptor.forClass(String.class);
when(mock.myFunction(param.capture())).thenAnswer(new Answer<String>() {
@Override
public String answer(InvocationOnMock invocation) throws Throwable {
return param.getValue();//return the captured value.
}
});
또는 람다 팬이라면 간단하게 수행하십시오.
//Use ArgumentCaptor to capture the value
ArgumentCaptor<String> param = ArgumentCaptor.forClass(String.class);
when(mock.myFunction(param.capture()))
.thenAnswer((invocation) -> param.getValue());
요약 : 전달 된 매개 변수를 캡처하려면 argumentcaptor를 사용하십시오. 나중에 대답은 getValue를 사용하여 캡처 된 값을 반환합니다.
This doesn´t work (anymore?).
내 인스턴스 에서이 작업을 수행 한다는 것이 무엇을 의미하는지 잘 모르겠습니다 . 2. 죄송합니다, 당신이 만들려고하는 시점에 명확하지 않습니다. 그 대답은 OP의 질문에만 해당됩니다.