Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Mocking Kotlin with MockK

Hadi Tok
September 20, 2019

Mocking Kotlin with MockK

Introduction to the mocking library MockK

Hadi Tok

September 20, 2019
Tweet

More Decks by Hadi Tok

Other Decks in Programming

Transcript

  1. Unit Testing • Unit: Smallest testable component (function, class) •

    Units are tested independently from each other • Other units with dependencies are mocked or faked
  2. Fake • Could have lightweight logic • Cut corners for

    testing purposes so can’t be used in production
  3. Mock • Not authentic or real, but without the intention

    to deceive. • Imitates objects to specify behaviour explicitly and enables full control over the object. • Usually backed with a library/framework
  4. Mocking • What functions and variables return • Check if

    the function calls and variable assignments are made with correct values
  5. Why MockK • Pure Kotlin • Easy to use Domain

    Specific Language(DSL) • Can also mock Java
  6. 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) } }
  7. @Test fun basicTest() { val userApi: UserApi = mockk() val

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

    userManager = UserManager(userApi) val userId = "123" val user: User = mockk() every { user.userId } returns userId }
  9. @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 }
  10. @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) }
  11. @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) }
  12. @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) } }
  13. @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) } }
  14. @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") }) } }
  15. @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()) } }
  16. Matchers • more(), less(), range() • eq(), neq(), refEq(), cmpEq()

    • isNull(), isNull(inverse=true) • match{}, matchNullable{}
  17. @MockK lateinit var userApi: UserApi @MockK lateinit var user: User

    val userId = “123" lateinit var userManager:UserManager
  18. @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 }
  19. @Test fun basicTest() { every { userApi.deleteUser(userId) } returns true

    val result = userManager.deleteUser(user) assert(result).toBe(true) verify { userApi.deleteUser(userId) } }
  20. object Calculator { fun add(first: Int, second: Int) = first

    + second } @Test fun objectMock() { val result = Calculator.add(1, 2) assert(result).toBe(3) }
  21. 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 }
  22. 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 }
  23. 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) }
  24. @Test fun staticMock() { val result = CalculatorStatic.add(1, 2) assert(result).toBe(3)

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

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

    mockkStatic(CalculatorStatic::class) every { CalculatorStatic.add(1, 2) } returns 42 val mockedResult = CalculatorStatic.add(1, 2) assert(mockedResult).toBe(42) }
  27. class Calculator { fun add(first: Int, second: Int) = first

    + second } @Test fun argumentCapturing() { val calculator:Calculator = mockk() }
  28. class Calculator { fun add(first: Int, second: Int) = first

    + second } @Test fun argumentCapturing() { val calculator:Calculator = mockk() every { calculator.add(any(), any()) } answers { firstArg<Int>() + secondArg<Int>() } }
  29. class Calculator { fun add(first: Int, second: Int) = first

    + second } @Test fun argumentCapturing() { val calculator:Calculator = mockk() every { calculator.add(any(), any()) } answers { firstArg<Int>() + secondArg<Int>() } val mockedResult = calculator.add(1, 2) assert(mockedResult).toBe(3) }
  30. data class User(val userId: String, val userName: String) interface UserApi

    { suspend fun deleteUser(userId: String): Boolean }
  31. 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) } }
  32. @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 }
  33. @Test fun basicTest() = runBlocking { every { user.userId }

    returns userId coEvery { userApi.deleteUser(userId) } returns true }
  34. @Test fun basicTest() = runBlocking { every { user.userId }

    returns userId coEvery { userApi.deleteUser(userId) } returns true val result = userManager.deleteUser(user) }
  35. @Test fun basicTest() = runBlocking { every { user.userId }

    returns userId coEvery { userApi.deleteUser(userId) } returns true val result = userManager.deleteUser(user) assert(result).toBe(true) coVerify { userApi.deleteUser(userId) } }
  36. Resources • https://mockk.io/ • Mocking is not rocket science: Basics:

    https://blog.kotlin-academy.com/mocking-is-not-rocke t-science-basics-ae55d0aadf2b