안녕하세요.
오늘은 mockkObject와 mockkStatic, mockkConstructor에 대해 알아보겠습니다.
mockkObject
kotlin의 object class와 enum class를 모킹할 때 사용하는 명령어 입니다.
spy 객체와 비슷하게 작동하며, 스터빙하지 않은 함수들은 기존 로직을 따릅니다.
사용을 다 하면, unmock을 해줘야 다른 테스트 함수에 영향을 주지 않습니다.
object
kotlin의 object class를 모킹해 원하는 값으로 스터빙 하는 예제를 살펴봅시다.
object code
object MySingleton {
fun functionOne(): String {
return "Original Function One"
}
fun functionTwo(): String {
return "Original Function Two"
}
}
unit test
mockkObject로 모킹해주고, 사용이 끝나면 unmockkObject를 해줍니다.
스터빙 하지 않은 함수는 기존 로직을 따르며, 이는 spy 객체와 유사합니다.
import io.mockk.every
import io.mockk.mockkObject
import io.mockk.unmockkAll
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
class MySingletonTest {
@BeforeEach
fun setUp() {
// MySingleton 객체를 모킹
mockkObject(MySingleton)
}
@AfterEach
fun tearDown() {
// 모킹 해제 (테스트 후 정리)
unmockkObject(MySingleton)
}
@Test
fun testMockkObject() {
// functionOne의 동작을 스터빙, functionTwo는 기존 로직을 따름
every { MySingleton.functionOne() } returns "Stubbed Function One"
// functionOne을 호출하면 스터빙된 결과가 나옴
assertEquals("Stubbed Function One", MySingleton.functionOne())
// functionTwo는 스터빙하지 않았기 때문에 원래의 로직이 동작
assertEquals("Original Function Two", MySingleton.functionTwo())
}
}
enum
kotlin의 enum class를 모킹할 때 사용할 수 있습니다.
enum code
enum class Status {
SUCCESS,
ERROR,
LOADING;
fun getStatusMessage(): String {
return when (this) {
SUCCESS -> "Operation was successful."
ERROR -> "There was an error."
LOADING -> "Loading in progress."
}
}
fun getStatusCode(): Int {
return when (this) {
SUCCESS -> 200
ERROR -> 500
LOADING -> 102
}
}
}
unit test
import io.mockk.every
import io.mockk.mockkObject
import io.mockk.unmockkAll
import io.mockk.unmockkObject
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
class StatusTest {
@BeforeEach
fun setUp() {
// Status enum 클래스를 모킹
mockkObject(Status.SUCCESS)
}
@AfterEach
fun tearDown() {
// 모킹 해제
unmockkObject(Status.SUCCESS)
}
@Test
fun testMockkObject() {
// getStatusMessage는 스터빙하여 다른 값을 반환
every { Status.SUCCESS.getStatusMessage() } returns "Mocked Success Message"
// 테스트: 스터빙된 메서드
assertEquals("Mocked Success Message", Status.SUCCESS.getStatusMessage())
// 테스트: 스터빙하지 않은 getStatusCode 메서드는 원래 로직을 따름
assertEquals(200, Status.SUCCESS.getStatusCode())
// 다른 상태는 스터빙되지 않았으므로 원래 로직을 따름
assertEquals("There was an error.", Status.ERROR.getStatusMessage())
assertEquals(500, Status.ERROR.getStatusCode())
}
}
mockkStatic
kotlin의 확장 함수와 java의 static method 를 스터빙 할 때 사용합니다.
spy 객체와 비슷하게 작동하며, 스터빙하지 않은 함수들은 기존 로직을 따릅니다.
사용을 다 하면, unmock을 해줘야 다른 테스트 함수에 영향을 주지 않습니다.
extension function
아래 블로그에서 설명했던 방식 중 top-level 방식으로 선언할 때 mockkStatic을 사용해 스터빙 합니다.
extension function 설명 : https://kdr06006.tistory.com/55
extension function code
data class Person(
val name: String,
val age: Int
)
fun Person.extensionTopLevel() = "$name, $age"
unit test
@Test
fun `test - top level extension`() {
val person = Person("Alice", 20)
mockkStatic(Person::extensionTopLevel)
every { person.extensionTopLevel() } returns "Kang, 11"
val result = person.extensionTopLevel()
assertEquals("Kang, 11", result)
unmockkStatic(Person::extensionTopLevel)
}
Java Static Method
java class에 들어있는 static method들을 일컫는 말입니다.
java static method code
public class MyJavaUtils {
public static int square(int x) {
return x * x;
}
public static String greet(String name) {
return "Hello, " + name;
}
}
unit test
import io.mockk.every
import io.mockk.mockkStatic
import io.mockk.unmockkStatic
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
class MyJavaUtilsTest {
@BeforeEach
fun setUp() {
// MyJavaUtils의 static 메서드를 모킹
mockkStatic(MyJavaUtils::class)
}
@AfterEach
fun tearDown() {
// 모킹 해제
unmockkStatic(MyJavaUtils::class)
}
@Test
fun testMockkStatic() {
// static 메서드 square를 스터빙하여 원하는 값을 반환
every { MyJavaUtils.square(2) } returns 10
// square 메서드를 호출하면 스터빙된 값이 반환됨
assertEquals(10, MyJavaUtils.square(2))
// greet 메서드는 모킹하지 않았으므로 원래 동작을 따름
assertEquals("Hello, Alice", MyJavaUtils.greet("Alice"))
}
}
mockkConstructor
생성자를 모킹한 후, 생성된 객체의 메서드를 스터빙할 때 사용합니다.
spy 객체와 비슷하게 작동하며, 스터빙하지 않은 함수들은 기존 로직을 따릅니다.
사용을 다 하면, unmock을 해줘야 다른 테스트 함수에 영향을 주지 않습니다.
class code
class MyClass(val name: String) {
fun greet(): String {
return "Hello, $name!"
}
fun farewell(): String {
return "Goodbye, $name!"
}
}
unit test
MyClass 생성자를 mockkConstructor로 모킹한 후, 생성된 객체의 메서드를 스터빙 합니다.
package com.example.unittest.mock
import io.mockk.*
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
class MyClassTest {
@BeforeEach
fun setUp() {
// MyClass의 생성자를 모킹
mockkConstructor(MyClass::class)
}
@AfterEach
fun tearDown() {
// 모킹 해제
unmockkConstructor(MyClass::class)
}
@Test
fun testMockkConstructor() {
// 생성자 호출 후 반환되는 객체의 greet 메서드를 스터빙
every { anyConstructed<MyClass>().greet() } returns "Mocked Greeting"
// 실제로 MyClass 생성자를 호출
val myObject = MyClass("John")
// 스터빙된 greet 메서드가 호출됨
assertEquals("Mocked Greeting", myObject.greet())
// farewell 메서드는 모킹하지 않았으므로 원래 로직을 따름
assertEquals("Goodbye, John!", myObject.farewell())
}
}
'Unit Test' 카테고리의 다른 글
[Unit Test] MockK (1) - Mock, Spy (0) | 2024.08.11 |
---|---|
[Unit Test] JUnit5 (2) - Parameterized Test (0) | 2024.07.08 |
[Unit Test] JUnit5 (1) - Use in Android Studio (1) | 2024.06.29 |