# Table of Contents
# Mockito
Mockito
(opens new window)라이브러리를 사용하면 객체의 Mock을 만들거나, 메소드를 Stubbing하거나, 검증할 수 있다.
# 설정
Mockito를 사용하려면 다음과 같은 의존성을 추가해야한다.
dependencies {
testImplementation "org.mockito:mockito-core:4.2.0"
androidTestImplementation "org.mockito:mockito-android:4.2.0"
}
Kotlin에서 Mockito를 사용하려면 mockito-inline
도 추가해야한다.
dependencies {
testImplementation "org.mockito:mockito-inline:4.2.0"
}
# InjectMocks
@InjectMocks mock(List.class)
# Mocking
Mock
객체를 만다는 것을 Mocking
한다고 한다.
예제를 살펴보자. Calculator
클래스를 다음과 같이 정의하자.
class Calculator {
fun plus(a: Int, b: Int): Int {
return a+b
}
fun minus(a: Int, b: Int): Int {
return a-b
}
fun multiply(a: Int, b: Int): Int {
return a*b
}
fun divide(a: Int, b: Int): Int {
return a/b
}
}
Calculator
클래스의 Mock은 다음과 같이 생성한다. Mock 객체가 저장되는 변수에는 @Mock
어노테이션을 추가한다. mock()
을 호출하면 Mock 객체가 생성된다.
import org.junit.Test
import org.mockito.Mock
import org.mockito.Mockito.mock
class CalculatorTest {
@Mock
lateinit var fakeCalculator: Calculator
@Test
fun test_calculator_plus() {
fakeCalculator = mock(Calculator::class.java)
}
}
# Stubbing
Calculator
의 add()
메소드를 Stubbing 해보자. Mock의 plus(3, 7)
을 호출하면 10을 반환하도록 Stubbing하고 있다.
class CalculatorTest {
@Mock
lateinit var fakeCalculator: Calculator
@Test
fun test_calculator_plus() {
// Create Mock
fakeCalculator = mock(Calculator::class.java)
// Stubbing
`when`(fakeCalculator.plus(3, 7)).thenReturn(10)
}
}
주목할 점은 Mock 객체를 사용하면 메소드의 실제 구현부를 호출하지 않는다는 것이다. Calculator
의 plus()
는 다음과 같이 구현되어있었다.
class Calculator {
fun plus(a: Int, b: Int): Int {
return a+b
}
// ...
}
그러나 Mock 객체와 Stub를 사용했으므로 10을 반환할 뿐 구현부 { return a+b }
가 실행되진 않는다.
이 외에도 Mockito
는 Stubbing을 위한 다양한 메소드를 제공한다.
# any()
위에서는 Stubing할 때 3, 7이라는 정확한 값을 넣어주었다.
`when`(fakeCalculator.plus(3, 7)).thenReturn(10)
any()
를 사용하면 어떤 값을 넣어도 10을 반환하도록 구현할 수 있다.
`when`(fakeCalculator.plus(anyInt(), anyInt())).thenReturn(10)
anyInt()
외에도 다양한 자료형을 지원하는 메소드가 있다.
- anyInt()
- anyString()
- anyBoolean()
- anyDouble()
- anyFloat()
- anyList()
# thenThrow()
메소드를 호출했을 때 Exception을 발생하도록 Stubbing할 수 있다.
`when`(fakeCalculator.divide(anyInt(), 0).thenThrow(ArithmeticException("by zero"))
# Spying
Mocking이 Mock 객체를 사용했다면 Spying
은 실제 객체를 사용한다. Spying
은 일부 메소드만 Stubbing
할 때 사용할 수 있다.
class CalculatorTest {
lateinit var calculator: Calculator
@Test
fun test_calculator_plus() {
// Spy Mock
calculator = spy(Calculator::class.java)
// Stubbing
`when`(calculator.plus(anyInt(), anyInt())).thenAnswer {
30
}
val result1 = calculator.plus(5, 20) // 30
val result2 = calculator.minus(20, 10) // 10
val result3 = calculator.multiply(10, 20) // 200
}
}
위 코드에서는 plus()
만 Stubbing하고 있다. 따라서 minus()
와 multiply()
를 호출하면 실제 구현부인 { return a-b }
와 { return a*b }
가 실행된다.
# 검증
Mockito
는 검증을 위한 다양한 메소드를 제공한다.
# verify()
verify()
를 사용하면 어떤 메소드가 호출되었는지, 몇 번 호출되었는지 등을 검증할 수 있다.
아래 코드는 fakeCalculator.plus(3, 7)
를 세 번 호출한 후 세 번 호출되었는지 검증하고있다.
class CalculatorTest {
@Mock
lateinit var fakeCalculator: Calculator
@Test
fun test_calculator_plus() {
// Create Mock
fakeCalculator = mock(Calculator::class.java)
// Stubbing
`when`(fakeCalculator.plus(3, 7)).thenReturn(10)
// Call plus(3, 7) 3 times
fakeCalculator.plus(3, 7)
fakeCalculator.plus(3, 7)
fakeCalculator.plus(3, 7)
// Check if called 3 times
verify(fakeCalculator, times(3)).plus(3, 7) // Test Success
}
}
# inOrder()
inOrder()
를 사용하면 메소드가 순서대로 호출되었는지 확인할 수 있다.
아래 코드는 fakeCalculator.plus(3, 7)
, fakeCalculator.minus(10, 4)
가 순서대로 호출되었는지 검증하고 있다.
class CalculatorTest {
@Mock
lateinit var fakeCalculator: Calculator
@Test
fun test_calculator_plus() {
// Create Mock
fakeCalculator = mock(Calculator::class.java)
// Stubbing
`when`(fakeCalculator.plus(3, 7)).thenReturn(10)
`when`(fakeCalculator.minus(10, 4)).thenReturn(6)
// Call Methods
fakeCalculator.plus(3, 7)
fakeCalculator.minus(10, 4)
// Verify Order
val inOrder = inOrder(fakeCalculator)
inOrder.verify(fakeCalculator).minus(10, 4)
inOrder.verify(fakeCalculator).plus(3, 7)
}
}
# thenAnswer()
thenAnswer()
를 사용하면 메소드를 호출했을 때 특정 구문을 호출하도록 Stubbing할 수 있다.
// Create Mock
fakeCalculator = mock(Calculator::class.java)
// Stubbing
`when`(fakeCalculator.plus(anyInt(), anyInt())).thenAnswer {
30
}
위 코드는 fakeCalculator.plus()
를 호출했을 때 30을 반환한다.
# 마치며
Mockito에 대한 더 자세한 내용은 이 곳 (opens new window)에서 확인할 수 있다.