programing

조롱당한 방법을 만들면 그에 전달된 인수를 반환한다.

prostudy 2022. 8. 29. 21:28
반응형

조롱당한 방법을 만들면 그에 전달된 인수를 반환한다.

다음과 같은 메서드 시그니처를 검토합니다.

public String myFunction(String abc);

Mockito는 메서드가 받은 것과 동일한 문자열을 반환할 수 있습니까?

Mockito에서 Answer를 생성할 수 있습니다.예를 들어 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()method는 에서는 스태틱한AdditionalAnswersMockito 1.9.5에서는 새로운 클래스이므로 적절한 스태틱 Import가 필요합니다.

Java 8에서는 이전 버전의 Mockito에서도 한 줄의 답변을 작성할 수 있습니다.

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

물론 이 기능은 사용법만큼 유용하지는 않습니다.AdditionalAnswersDavid Wallace가 제안했지만 "on the fly" 인수를 변환하려는 경우 유용할 수 있습니다.

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

public class RoomService {
    public Room findByName(String roomName) {...}
    public void persist(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"));
}

이것은 꽤 오래된 질문이지만 나는 여전히 관련이 있다고 생각한다.또한 허용되는 답변은 String에만 적용됩니다.한편, Mockito 2.1이 있어, Import가 변경되고 있기 때문에, 현재의 회답은 다음과 같습니다.

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.my함수는 다음과 같습니다.

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

이건 좀 오래된 건데, 같은 문제가 있어서 왔어요.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"))
}

Argument Captor를 사용하면 이 작업을 수행할 수 있습니다.

이렇게 콩 기능이 있다고 상상해 보세요.

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

개요:전달된 매개 변수를 캡처하려면 argumentcapter를 사용합니다.나중에 getValue를 사용하여 캡처한 값을 반환합니다.

verify()를 ArgumentCaptor 및 ArgumentCaptor와 조합하여 테스트 실행을 확인하고 ArgumentCaptor를 사용하여 인수를 평가할 수 있습니다.

ArgumentCaptor<String> argument = ArgumentCaptor.forClass(String.class);
verify(mock).myFunction(argument.capture());
assertEquals("the expected value here", argument.getValue());

인수 값은 인수.getValue()를 통해 추가 조작/체크/무엇을 위해 액세스할 수 있습니다.

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

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

언급URL : https://stackoverflow.com/questions/2684630/making-a-mocked-method-return-an-argument-that-was-passed-to-it

반응형