$30 off During Our Annual Pro Sale. View Details »

Mocking Kotlin with MockK

Mocking Kotlin with MockK

Hadi Tok

March 23, 2019
Tweet

More Decks by Hadi Tok

Other Decks in Programming

Transcript

  1. KOTLIN'DE MOCKLAMA
    VE MOCKK

    View Slide

  2. BEN KIMIM
    ➤ Lead Android Dev @CizitzenMe
    ➤ https://haditok.com

    View Slide

  3. UNIT TESTING NEDIR?
    ➤ Unit: En küçük test edilebilir birim (Class, Function)
    ➤ Birimler diğer birimlerden bağımısız olarak test edilir.
    ➤ Diğer birimler Mock veya Fake ile değiştirilir.

    View Slide

  4. TEST EDILEBILIR KOD
    ➤ Separations of concerns
    ➤ Dependency injection
    ➤ Clean code

    View Slide

  5. FAKE
    ➤ Anlamı: Sahte
    ➤ Daha önceden belirlenmiş değerleri dönerek kontrollü bir
    ortam sağlama

    View Slide

  6. MOCKING NEDIR?
    Kuzey Alaycı kuşu (Mimus polyglottos)

    View Slide

  7. MOCK
    ➤ Anlamı: Taklit, Alay
    ➤ Unit testlerde test ettiğimiz birimin ihtiyacı olan objeleri
    objeleri taklit ederek, bu objeler üzerinde tam kontrol sağlar

    View Slide

  8. NELERI KONTROL EDIYORUZ?
    ➤ Değişken ve fonksiyonların döneceği değerleri
    ➤ Fonksiyonların doğru parametreler ile çağırılıp çağrılmadığını

    View Slide

  9. NEDEN MOCKK
    ➤ Saf Kotlin için bir framework
    ➤ Domain Specific Language(DSL)

    View Slide

  10. data class User(val userId: String, val userName: String)

    View Slide

  11. data class User(val userId: String, val userName: String)
    interface UserApi {
    fun deleteUser(userId: String): Boolean
    }

    View Slide

  12. data class User(val userId: String, val userName: String)
    interface UserApi {
    fun deleteUser(userId: String): Boolean
    }
    class UserManager(private val userApi: UserApi) {
    fun deleteUser(user: User): Boolean {
    return userApi.deleteUser(user.userId)
    }
    }

    View Slide

  13. @Test
    fun basicTest() {
    val userApi: UserApi = mockk()
    }

    View Slide

  14. @Test
    fun basicTest() {
    val userApi: UserApi = mockk()
    val userManager = UserManager(userApi)
    }

    View Slide

  15. @Test
    fun basicTest() {
    val userApi: UserApi = mockk()
    val userManager = UserManager(userApi)
    val userId = "123"
    val user: User = mockk()
    every { user.userId } returns userId
    }

    View Slide

  16. @Test
    fun basicTest() {
    val userApi: UserApi = mockk()
    val userManager = UserManager(userApi)
    val userId = "123"
    val user: User = mockk()
    every { user.userId } returns userId
    every { userApi.deleteUser(userId) } returns true
    }

    View Slide

  17. @Test
    fun basicTest() {
    val userApi: UserApi = mockk()
    val userManager = UserManager(userApi)
    val userId = "123"
    val user: User = mockk()
    every { user.userId } returns userId
    every { userApi.deleteUser(userId) } returns true
    val result = userManager.deleteUser(user)
    }

    View Slide

  18. @Test
    fun basicTest() {
    val userApi: UserApi = mockk()
    val userManager = UserManager(userApi)
    val userId = "123"
    val user: User = mockk()
    every { user.userId } returns userId
    every { userApi.deleteUser(userId) } returns true
    val result = userManager.deleteUser(user)
    assert(result).toBe(true)
    }

    View Slide

  19. @Test
    fun basicTest() {
    val userApi: UserApi = mockk()
    val userManager = UserManager(userApi)
    val userId = "123"
    val user: User = mockk()
    every { user.userId } returns userId
    every { userApi.deleteUser(userId) } returns true
    val result = userManager.deleteUser(user)
    assert(result).toBe(true)
    verify { userApi.deleteUser(userId) }
    }

    View Slide

  20. @Test
    fun basicTest() {
    val userApi: UserApi = mockk()
    val userManager = UserManager(userApi)
    val userId = "123"
    val user: User = mockk()
    every { user.userId } returns userId
    every { userApi.deleteUser(userId) } returns true
    val result = userManager.deleteUser(user)
    assert(result).toBe(true)
    verify { userApi.deleteUser(match { it.startsWith("12") }) }
    }

    View Slide

  21. @Test
    fun basicTest() {
    val userApi: UserApi = mockk()
    val userManager = UserManager(userApi)
    val userId = "123"
    val user: User = mockk()
    every { user.userId } returns userId
    every { userApi.deleteUser(userId) } returns true
    val result = userManager.deleteUser(user)
    assert(result).toBe(true)
    verify { userApi.deleteUser(any()) }
    }

    View Slide

  22. @MockK
    lateinit var userApi: UserApi
    @MockK
    lateinit var user: User
    val userId = “123"
    lateinit var userManager:UserManager
    @Before
    fun initTests() {
    MockKAnnotations.init(this)
    userManager = UserManager(userApi)
    every { user.userId } returns userId
    }
    @Test
    fun basicTest() {
    every { userApi.deleteUser(userId) } returns true
    val result = userManager.deleteUser(user)
    assert(result).toBe(true)
    verify { userApi.deleteUser(userId) }
    }

    View Slide

  23. OBJECT MOCK

    View Slide

  24. object Calculator {
    fun add(first: Int, second: Int) = first + second
    }

    View Slide

  25. object Calculator {
    fun add(first: Int, second: Int) = first + second
    }
    @Test
    fun objectMock() {
    val result = Calculator.add(1, 2)
    assert(result).toBe(3)
    }

    View Slide

  26. object Calculator {
    fun add(first: Int, second: Int) = first + second
    }
    @Test
    fun objectMock() {
    val result = Calculator.add(1, 2)
    assert(result).toBe(3)
    mockkObject(Calculator)
    }

    View Slide

  27. object Calculator {
    fun add(first: Int, second: Int) = first + second
    }
    @Test
    fun objectMock() {
    val result = Calculator.add(1, 2)
    assert(result).toBe(3)
    mockkObject(Calculator)
    every { Calculator.add(1, 2) } returns 42
    }

    View Slide

  28. object Calculator {
    fun add(first: Int, second: Int) = first + second
    }
    @Test
    fun objectMock() {
    val result = Calculator.add(1, 2)
    assert(result).toBe(3)
    mockkObject(Calculator)
    every { Calculator.add(1, 2) } returns 41
    val mockedResult = Calculator.add(1, 2)
    }

    View Slide

  29. object Calculator {
    fun add(first: Int, second: Int) = first + second
    }
    @Test
    fun objectMock() {
    val result = Calculator.add(1, 2)
    assert(result).toBe(3)
    mockkObject(Calculator)
    every { Calculator.add(1, 2) } returns 41
    val mockedResult = Calculator.add(1, 2)
    assert(mockedResult).toBe(42)
    }

    View Slide

  30. STATIC MOCK

    View Slide

  31. public class CalculatorStatic {
    static int add(int first, int second){
    return first+second;
    }
    }

    View Slide

  32. @Test
    fun staticMock() {
    val result = CalculatorStatic.add(1, 2)
    assert(result).toBe(3)
    }

    View Slide

  33. @Test
    fun staticMock() {
    val result = CalculatorStatic.add(1, 2)
    assert(result).toBe(3)
    mockkStatic(CalculatorStatic ::class)
    }

    View Slide

  34. @Test
    fun staticMock() {
    val result = CalculatorStatic.add(1, 2)
    assert(result).toBe(3)
    mockkStatic(CalculatorStatic ::class)
    every { CalculatorStatic.add(1, 2) } returns 42
    }

    View Slide

  35. @Test
    fun staticMock() {
    val result = CalculatorStatic.add(1, 2)
    assert(result).toBe(3)
    mockkStatic(CalculatorStatic ::class)
    every { CalculatorStatic.add(1, 2) } returns 41
    val mockedResult = CalculatorStatic.add(1, 2)
    }

    View Slide

  36. @Test
    fun staticMock() {
    val result = CalculatorStatic.add(1, 2)
    assert(result).toBe(3)
    mockkStatic(CalculatorStatic ::class)
    every { CalculatorStatic.add(1, 2) } returns 41
    val mockedResult = CalculatorStatic.add(1, 2)
    assert(mockedResult).toBe(42)
    }

    View Slide

  37. COROUTINES

    View Slide

  38. data class User(val userId: String, val userName: String)
    interface UserApi {
    suspend fun deleteUser(userId: String): Boolean
    }

    View Slide

  39. data class User(val userId: String, val userName: String)
    interface UserApi {
    suspend fun deleteUser(userId: String): Boolean
    }
    class UserManager(private val userApi: UserApi) {
    suspend fun deleteUser(user: User): Boolean {
    return userApi.deleteUser(user.userId)
    }
    }

    View Slide

  40. @Test
    fun basicTest() = runBlocking {
    }

    View Slide

  41. @Test
    fun basicTest() = runBlocking {
    val userApi: UserApi = mockk()
    val userManager = UserManager(userApi)
    val userId = "123"
    val user: User = mockk()
    every { user.userId } returns userId
    }

    View Slide

  42. @Test
    fun basicTest() = runBlocking {
    val userApi: UserApi = mockk()
    val userManager = UserManager(userApi)
    val userId = "123"
    val user: User = mockk()
    every { user.userId } returns userId
    coEvery { userApi.deleteUser(userId) } returns true
    }

    View Slide

  43. @Test
    fun basicTest() = runBlocking {
    val userApi: UserApi = mockk()
    val userManager = UserManager(userApi)
    val userId = “123"
    val user: User = mockk()
    every { user.userId } returns userId
    coEvery { userApi.deleteUser(userId) } returns true
    val result = userManager.deleteUser(user)
    }

    View Slide

  44. @Test
    fun basicTest() = runBlocking {
    val userApi: UserApi = mockk()
    val userManager = UserManager(userApi)
    val userId = “123"
    val user: User = mockk()
    every { user.userId } returns userId
    coEvery { userApi.deleteUser(userId) } returns true
    val result = userManager.deleteUser(user)
    assert(result).toBe(true)
    coVerify { userApi.deleteUser(userId) }
    }

    View Slide

  45. LIMITASYONLAR
    ➤ final static
    ➤ inline fonksiyonlar

    View Slide

  46. UNIT TESTS WITHOUT INTEGRATION TESTS (ZORUNLU GIF)

    View Slide

  47. TEŞEKKÜRLER
    HTTPS://MOCKK.IO/

    View Slide