Local JUnit Test on Objectbox

WindSekirun (wind.seo)·2022년 4월 26일
0

이 글은 기존 운영했던 WordPress 블로그인 PyxisPub: Development Life (pyxispub.uzuki.live) 에서 가져온 글 입니다. 모든 글을 가져오지는 않으며, 작성 시점과 현재 시점에는 차이가 많이 존재합니다.

작성 시점: 2018-11-05

도입

최근 앱 내부에 모델을 저장해야 되는 일이 있을 때에 Eventbus로 유명한 Greenrobot가 제작하는 ObjectBox 를 많이 활용한다.

Entity, 즉 ObjectBox와 프로젝트를 연결하는 Manager 라는 클래스를 별도로 제작하여 이 클래스 안에서 ObjectBox에 관련된 작업 (CRUD, 정렬, 검색 등)을 진행하고 하위 코드(ViewModel) 단에서 이 Manager 클래스를 Inject받아 RxJava로 활용하는 방식이다.

이 방식에 약간의 문제점이 있다면 하위 코드를 작성하기 전까지는 해당 Manager 클래스를 테스트하기 어렵다는 점인데, 다행히 ObjectBox는 JUnit를 통한 단위 테스트를 제공한다.

따라서 이 글에서는 간단히 JUnit로 ObjectBox 와 RxJava2를 테스트하는 방법을 살펴보려 한다.

테스트 코드의 언어는 Java를 사용했다.

ObjectBox 테스트 환경 제작

ObjectBox에서는 JUnit로 테스트할 때에 OS(Windows / macOS / Linux)에 맞는 바이너리 파일을 받아와 mdb 파일을 생성하고 데이터를 실제로 넣는 작업을 진행한다.

먼저, JUnit 클래스를 만들고 작업이 시작되기 전과 후에 Objectbox에 대한 작업을 진행한다.

private static final File TEST_DIRECTORY = new File("objectbox-example/test-db");
  private BoxStore mBoxStore;

  @Before
  public void setUp() throws Exception {
      // delete database files before each test to start with a clean database
      BoxStore.deleteAllFiles(TEST_DIRECTORY);
      mBoxStore = MyObjectBox.builder()
              // add directory flag to change where ObjectBox puts its database files
              .directory(TEST_DIRECTORY)
              // optional: add debug flags for more detailed ObjectBox log output
              .debugFlags(DebugFlags.LOG_QUERIES | DebugFlags.LOG_QUERY_PARAMETERS)
              .build();
  }

  @After
  public void tearDown() throws Exception {
      if (mBoxStore != null) {
          mBoxStore.close();
          mBoxStore = null;
      }
      BoxStore.deleteAllFiles(TEST_DIRECTORY);
  }

@Before 가 붙은 setUp() 의 메서드 실행 결과로 BoxStore 객체가 생성되므로, Box 객체를 받아올 때에는mBoxStore.boxFor(Class) 를 실행하면 된다.

그 다음 @After 가 붙은 tearDown 에서는 테스트가 종료될 때 생성된 DB 파일을 지워 이전의 테스트 결과가 현재의 테스트 결과에 영향을 주지 않게 변경한다.

ObjectBox 작업 테스트하기

본 예제에서 테스트할 작업은 DB에서 시작 날짜와 종료 날짜 사이의 데이터를 날짜 기준으로 정렬하여 리스트를 가져오는 작업이다.

public Observable<List<CalendarData>> getCalendarDataList(Calendar startCalendar, Calendar endCalendar) {
    return Observable.create(emitter -> {
        int startDay = CalendarUtils.getFormatDay(startCalendar);
        int endDay = CalendarUils.getFormatDay(endCalendar);

        List<CalendarData> sorted = Stream.of(mBox.query()
                .between(CalendarData_.formatDay, startDay, endDay)
                .build()
                .find())
                .sortBy(value -> value.formatDay)
                .toList();

        emitter.onNext(sorted);
    });
}

그리고 위 메서드에 대해 테스트 케이스를 작성하면, RxJava 구독을 성공했고 에러 없이 작업이 될 경우일 것이다.

@Test
public void getCalendarDataWeakList() {
    TestObserver<List<CalendarData>> dataTestObserver = new TestObserver<>();

    Calendar startCalendar = Calendar.getInstance();
    Calendar endCalendar = Calendar.getInstance();

    startCalendar.set(Calendar.DAY_OF_WEEK, 1);
    endCalendar.set(Calendar.DAY_OF_WEEK, endCalendar.getActualMaximum(Calendar.DAY_OF_WEEK));

    mCalendarDataManager.getCalendarDataList(startCalendar, endCalendar)
            .subscribe(dataTestObserver);

    dataTestObserver.assertSubscribed()
            .assertNoErrors();
}

여기서 TestObserver 라는 클래스가 있는데, TestObserver 는 RxJava의 다양한 행동을 검증할 수 있는 메서드를 제공한다.

상기한 '구독을 성공했다' 에 대한 검증은 assertSubscribed()를, 에러 없이 작업이 될 경우는 assertNoErrors() 를 사용했다.

위 테스트 케이스를 구동하면 아래와 같은 로그가 나온다.

[INFO ] Creating query #1 for CalendarData with 1 condition(s)
[INFO ] Finding using query #1
[INFO ] Parameters for query #1:
formatDay between 20181104 and 20181110
[INFO ] Creating query #2 for CalendarData with 1 condition(s)
[INFO ] Finding scalars using query #2
[INFO ] Creating query #3 for CalendarData with 1 condition(s)
[INFO ] Finding using query #3
[INFO ] Parameters for query #3:
formatDay between 20181104 and 20181110

Process finished with exit code 0

setUp 메서드에서 설정한 대로 ObjectBox가 표시하는 디버그 로그가 나오면서, 작업이 성공한다.

정리

이처럼 ObjectBox와 RxJava가 실제 환경과 거의 같은 환경을 제공하는 덕분에, 하위 코드가 작성되기 전 해당 클래스에 대한 검증이 가능했다.

profile
Android Developer @kakaobank

0개의 댓글