본문 바로가기

Flutter

Flutter Mockito를 이용한 API 통신 Unit Test

API 통신 기능을 unit test 할 때 실제 API를 호출하여 진행하면 몇 가지 문제가 있다.

  • 실제 API를 요청하게 되면 test 성능이 저하될 수 있다.
  • 서버의 이상 유무에 따라 응답 값이 달라질 수 있고, 이 경우 테스트가 실패하게 된다.
  • 모든 성공, 실패를 테스트하기는 무리가 있다.

위와 같은 이유로 Flutter에서는 Mock 객체를 생성하여 다양한 케이스를 테스트할 수 있고, 이는 annotation과 code generation을 제공하는 mockito 패키지를 이용하여 진행하면 된다.

 

Example

Mockito Package

https://pub.dev/packages/mockito

 

mockito | Dart Package

A mock framework inspired by Mockito with APIs for Fakes, Mocks, behavior verification, and stubbing.

pub.dev

dev_dependencies:
  flutter_test:
    sdk: flutter
  build_runner: ^2.3.3
  mockito: ^5.4.0

 

 

Pixabay에서 제공하는 이미지 검색 API 통신을 테스트 해보려고 한다. 

 

1. 테스트 할 메서드 작성

테스트 시 Dio Mock 객체를 받을 수 있도록 파라미터에 Dio를 추가해준다.

 Future<List<Photo>> fetch(String query, {Dio? dio}) async {
    dio ??= Dio();

    final response = await dio.get(
      "$baseUrl?key=$key&q=$query&image_type=photo&pretty=true",
    );

    final hits = response.data["hits"] as List;
    return hits.map((e) => Photo.fromJson(e)).toList();
  }

 

2. 테스트 코드 작성

pixabay_api_test.dart

성공 케이스를 테스트할 것이기 때문에 성공 시 데이터를 임의로 정의해준다.

Map<String, dynamic> json = {
    "total":8740,
    "totalHits":500,
    "hits":[
        {
            "id":2681039,
            "pageURL":"https://pixabay.com/photos/phone-wallpaper-watercolor-painting-2681039/",
            "type":"photo",
            "tags":"phone wallpaper, watercolor, painting",
            "previewURL":"https://cdn.pixabay.com/photo/2017/08/25/18/48/watercolor-2681039_150.jpg",
            "previewWidth":99,
            "previewHeight":150,
            "webformatURL":"https://pixabay.com/get/g4294e9afbf2e8811de22692f01d36829bb92a29d6b16bb14907db22b665c939ca1a0dac346e921298c381c365cd5fd4ea928dfa11c2dc8d41ce8f9cf37fd61d6_640.jpg",
            "webformatWidth":424,
            "webformatHeight":640,
            "largeImageURL":"https://pixabay.com/get/g070184928be6f74c342546d1db00d7d4bc3e248539e1bd9157bf7a656ee26fadfcf2285fa298c658245febfd4341aee82d4aba07205b4d02976e741ec40c2694_1280.jpg",
            "imageWidth":3264,
            "imageHeight":4928,
            "imageSize":5021313,
            "views":1254783,
            "downloads":976006,
            "collections":1948,
            "likes":1247,
            "comments":135,
            "user_id":4894494,
            "user":"eluela31",
            "userImageURL":"https://cdn.pixabay.com/user/2017/04/24/19-55-29-652_250x250.jpg"
        },
        ...
    ]
};

 

위와 같이 임의로 성공 시의 데이터를 정의하고 이를 응답 값으로 설정해주는 액션을 취하기 위해 새로운 요청 객체를 생성해줘야하는데, 이 것이 Mock 객체이다.

어노테이션을 통해 Mock 객체를 생성할 수 있고, 나는 Dio를 사용하기 때문에 @GenerateMock([Dio])의 형태로 어노테이션을 사용했다. 이 후 Terminal에 코드 생성 명령어를 입력하면 pixabay_api_test.mock.dart  파일이 생성된다.

 

@GenerateMocks([Dio])
void main() {}
flutter pub run build_runner build

main method

생성한 MockDio 객체와 mockito 패키지에서 제공하는 when 메서드를 이용하여 성공 조건을 설정해줄 수 있다.

when의 인자로 테스트하려는 요청 함수를 지정하고 when의 반환 클래스인 PostExpectation 클래스의 thenAnswer 메서드로 응답 값을 설정해준다.

마지막으로 verify 메서드를 통해 인자로 지정된 메서드가 호출되었는지 확인한다.

@GenerateMocks([Dio])
void main() {
  test("pixabay api test", () async {
    final api = PixabayApi();

    final dio = MockDio();

    when(dio.get(
      "${PixabayApi.baseUrl}?key=${PixabayApi.key}&q=iphone&image_type=photo&pretty=true",
    )).thenAnswer((_) async => Response(
          data: json,
          statusCode: 200,
          requestOptions: RequestOptions(),
        ));

    final result = await api.fetch("iphone", dio: dio);

    expect(result.first.id, 2681039);

    verify(dio.get(
      "${PixabayApi.baseUrl}?key=${PixabayApi.key}&q=iphone&image_type=photo&pretty=true",
    ));
  });
}

Result

 

'Flutter' 카테고리의 다른 글

flutter_gen 패키지를 이용하여 asset 사용하기  (0) 2023.11.27
Flutter MVVM Architecture  (0) 2023.05.30
Flutter InheritedWidget  (0) 2023.04.18
뒤늦게 정리하는 Flutter riverpod 개념  (0) 2023.04.06
Debounce와 Throttle  (0) 2023.04.06