Hun's Blog

[Android] Android Test 4 - Mockito 본문

Android

[Android] Android Test 4 - Mockito

jhk-im 2020. 3. 22. 09:02

Mockito

이미지1 Mockito Logo



Mockito를 설명하기 위해선 Unit test의 단점에 대해 생각해봐야한다.

Unit test의 단점 
* 많은 java 클래스가 다른 클래스에 의존하기 때문에  Unit test는 클래스별로 테스트해야한다.

ex)
LocalDatabaseManager 
- 로컬 데이터베이스에서 특정 정보를 꺼내오거나 입력하는 일을 담당하는 클래스이다. 
해당 클래스를 Unit 단위로 테스트하려한다. 하지만 해당 클래스는 데이터베이스의 테이블을 생성하고 관리하는 클래스에게 상당히 의존적이다. 특정 정보를 꺼내오거나 입력하는 메소드들을 테스트하기 위해 Test 클래스를 생성할 때 메소드 뿐만아니라 테스트 테이블까지도 구현해야만 테스트가 가능하다. 


Mock으로 해결 
mock 객체는 수동으로 생성하거나 mock 프레임 워크를 사용하여 클래스를 시뮬레이션 할 수 있다. 위의 예를 해결해 보자면 mock 객체는 데이터 공급자가 된다.
앱은 실제로 구현된 로컬 데이터베이스를 사용하겠지만 테스트를 위해서는 테스트 조건이 항상 동일한 mock 객체를 제공받아 테스트에 사용하면 된다.
mock 객체는 메소드 호출을 위해 정의된 클래스 또는 인터페이스에 대한 더미오브젝트이다.
Mock 프레임워크를 사용하면 mock 객체를 간단하게 만들 수 있다.

Mock (모조품) 이라는 이름처럼 mock 객체는 가짜 데이터 제공자가 되어 테스트시에 데이터베이스에 의존하지 않고 데이터베이스에 관련된 메소드들을 테스트 할 수 있도록 도와준다. 

Mockito = Mock Framework 
JUnit과 함께 사용할 수 있는 대중적인 mock프레임워크이다.
Mockito를 사용하면 mock 객체를 생성하고 구성할 수 있다.


사용법

1. app - build.gradle

1
2
//Mockito
testImplementation 'org.mockito:mockito-core:2.23.0'
 

를 통해 객체의 반환값을 임의로 정해 Unit Test를 할 수 있다.
객체에 데이터를 추가하는 다양한 기능 및 검증을 할 수 있는 메소드가 제공된다.

2. MockitoExample / MockitoExampleTest 생성



MockitoExmaple

1
2
3
4
5
6
7
8
public class MockitoExample {
    private String name;
    private int age;
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
}
 
 


MockitoExampleTest

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class MockitoExampleTest {
    @Test
    public void test() {
        //mock객체 생성
 
        MockitoExample p = mock(MockitoExample.class);
        //p 객체가 존재하는지 확인
 
        assertTrue( p != null);
        //when 메소드를 통애 p 객체의 getName, getAga 반환값을 지정
 
        when(p.getName()).thenReturn("BlackJin");
        when(p.getAge()).thenReturn(27);
        //p 의 반환 값이 기대값과 같은지 확인
 
        assertTrue("BlackJin".equals(p.getName()));
        assertTrue(27 == p.getAge());
 
    }
}
 
 


mock() -> mock 객체를 생성한다.
thenReturn()  -> mock 객체에 반환값을 지정

정리 - 
이전에 JUnit에서의 테스트 시나리오는 메소드 그 자체의 기능에 대한 것이었다. 예를 들면 CoffeeOrder객체가 커피 수량이 지정되면 그 값들로 총 금액을 계산하는 것 처럼 객체에 특정 값들이 잘 입력된다면 다른 클래스와 상관없이 Test 할 수 있는 것들이었다. 

CoffeeOrder는 정해진 커피가격인 상수를 가지고있다. 
여기서 만약 커피가격을 정해진 상수로 쓰는 것이아니라 현재 날짜에 따라 월별 이벤트 할인으로 값을 계산해서 가격을 책정하는 CoffeeEventPrice 클래스에 값을 넘겨 계산을 한 후 리턴받은 커피 값으로 가격을 책정해야 하는 상황이라면 어떨까? 
단순히 커피값을 수량에 따라 계산하는 메소드의 기능을 테스트하기 위한 것인데 가격책정때문에 셋팅해야 할 것이 더 많아진 것이다. 

Mockito 프레임워크를 사용해 CoffeeEventPrice객체를 Mock 객체 = 가짜 객체로 만들어서 위의 예처럼 리턴값이라든지 특정 값들을 지정해두고 사용한다면 테스트가 한결 수월해질 것이다. 

이처럼 mockito framework는 Unit Test시 의존성때문에 테스트를 어렵게 하는 객체들을 가짜객체로 만들어 값들을 손쉽게 셋팅하여 사용함으로써 더이상 해당클래스에 의존하지 않고도 쉽게 Test를 구현할 수 있도록 도와준다. 

Local Database 구현 계획이 있기 때문에 mock을 활용해서 Test를 구현해보고 조금더 다양한 기능들을 찾아보고 추가로 더 정리해야 할 것 같다. 


참고
https://alexzh.com/android-testing-mockito-robolectric/
이미지
https://github.com/mockito/mockito

 

mockito/mockito

Most popular Mocking framework for unit tests written in Java - mockito/mockito

github.com

 

Android testing: Mockito and Robolectric (Part 2) - Android development and testing

This is a second article from series of articles about testing Android project. First article about “Unit testing” you…

alexzh.com