자바/단위테스트

Mockito 사용

끄적끄적 2022. 6. 18. 20:24

테스트를 위해 외부 연동부분을 Stup이나 Mock으로 대체할 수 있다.

public class AddressRetriever {
   private Http http;

   public AddressRetriever(Http http) {
      this.http = http;
   }

   public Address retrieve(double latitude, double longitude)
           throws IOException, ParseException {
      String parms = String.format("lat=%.6flon=%.6f", latitude, longitude);
      String response = http.get(
              "http://open.mapquestapi.com/nominatim/v1/reverse?format=json&"
                      + parms);

      JSONObject obj = (JSONObject)new JSONParser().parse(response);
      // ...
}

위와 같은 AddressRetriever 클래스의 retrieve 메서드를 테스트하고 싶은데, http.get 외부 호출을 Mock처리하고 싶다.
아래와 같이 Mockito를 이용해서 when ~ thenReturn구문으로 사전에 행도을 정의하고 생성자에 넣어줄 수 있다.

public class AddressRetrieverTest2 {
   @Test
   public void answersAppropriateAddressForValidCoordinates() 
         throws IOException, ParseException {
      Http http = mock(Http.class);
      when(http.get(contains("lat=38.000000&lon=-104.000000"))).thenReturn(
            "{\"address\":{"
            + "\"house_number\":\"324\","
           // ...
            + "\"road\":\"North Tejon Street\","
            + "\"city\":\"Colorado Springs\","
            + "\"state\":\"Colorado\","
            + "\"postcode\":\"80903\","
            + "\"country_code\":\"us\"}"
            + "}");
      AddressRetriever retriever = new AddressRetriever(http);

      Address address = retriever.retrieve(38.0,-104.0);

생성자로 주입할 수 없는 환경이면 아래와 같이 할 수 도 있다.

public class AddressRetriever {
   private Http http = new HttpImpl();

   public Address retrieve(double latitude, double longitude)
         throws IOException, ParseException {
      String parms = String.format("lat=%.6f&lon=%.6f", latitude, longitude);
      String response = http.get(
         "http://open.mapquestapi.com/nominatim/v1/reverse?format=json&"
         + parms);

      JSONObject obj = (JSONObject)new JSONParser().parse(response);
      // ...

위와 같이 생성자로 주입이 불가능하면 @Mock으로 Mock객체를 정의하고,  MockitoAnnotations.initMocks(this) 로 @InjectMocks 붙은 필드(AddressRetriever)를 가져와서 목객체를 거기에 주입한다.

public class AddressRetrieverTest {
   @Mock private Http http;
   @InjectMocks private AddressRetriever retriever;
   
   @Before
   public void createRetriever() {
      retriever = new AddressRetriever();
      MockitoAnnotations.initMocks(this);
   }

   @Test
   public void answersAppropriateAddressForValidCoordinates() 
         throws IOException, ParseException {
      when(http.get(contains("lat=38.000000&lon=-104.000000")))
         .thenReturn("{\"address\":{"
                        + "\"house_number\":\"324\","
         // ...
                        + "\"country_code\":\"us\"}"
                        + "}");

      Address address = retriever.retrieve(38.0,-104.0);
반응형