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

Mockk - Saeed Masoumi

Mockk - Saeed Masoumi

Saeed Masoumi

October 19, 2018
Tweet

More Decks by Saeed Masoumi

Other Decks in Programming

Transcript

  1. Mocks Aren't Stubs • Mock • initialize -> set expectations

    -> exercise -> verify • Stub • initialize -> exercise -> verify • Class that implements the interface/class you are faking for testing purposes • But, There is no such difference, call whatever you want (KISS)
  2. SUT and DOCs • The System Under Test (SUT) refers

    to a system that is being tested for correct operation. • Depended On Component (DOC), is a collaborator, component that is required by SUT to fulfill its duties
  3. How it works • mockk your objects • For every

    object, set its behavior • verify them
  4. How it works val torch = mockk<Torch>() every { torch.turnOn()

    } returns OFF val status = torch.turnOn() assertEquals(OFF, status) verify { torch.turnOn() }
  5. Object Mocking mockkObject(Math) assertEquals(3, Math.sum(1, 2)) every { Math.sum(any(), 2)

    } returns 22 assertEquals(22, Math.sum(1, 2)) Also can be used for Enum mocking
  6. Constructor Mocking • Call init block • Because sometimes a

    testing method will return a new instance of an object
  7. Extension Function Mocking data class Obj(val value: Int) class Ext

    { fun Obj.extensionFunc() = value + 5 } with(mockk<Ext>()) { every { Obj(5).extensionFunc() } returns 11 assertEquals(11, Obj(5).extensionFunc()) verify { Obj(5).extensionFunc() } } Object/Class Wide
  8. Extension Function Mocking data class Obj(val value: Int) fun Obj.extensionFunc()

    = value + 5 mockkStatic("com.yourcompany.FileKt") every { Obj(5).extensionFunc() } returns 11 assertEquals(11, Obj(5).extensionFunc()) verify { Obj(5).extensionFunc() } Module Wide
  9. Spying • spyk() means a copy of given object which

    allows to mix mocks and real methods/field • mockk(relaxed = true) (relaxed mock) is a mock with no restriction to set behavior, So it uses simple value like 0 or null for mocked objects
  10. Private Mocking class Profile { fun info() = "name: ${name()},

    cardNumber ${cardNumber()}" fun name() = "Saeed" private fun cardNumber() = "****" } val mock = spyk<Profile>() every { mock["cardNumber"]() } returns "1234" assertEquals("name: Saeed, cardNumber 1234", mock.info())
  11. Private Mocking • recordPrivateCalls in Spyk • Verbose syntax for

    dynamic calls and property backing fields
 every { mock getProperty "abc" } every { mock setProperty "xyz" value less(5) } every { mock invoke "foo" withArguments listOf("a", "b") } every { mock.property = any() } propertyType Int::class answers { fieldValue += value } •
  12. Implement Interface class Profile { fun info() = "name: ${name()},

    cardNumber ${cardNumber()}" fun name() = "Saeed" private fun cardNumber() = "****" }
  13. Implement Interface open class Profile { fun info() = "name:

    ${name()}, cardNumber ${cardNumber()}" fun name() = "Saeed" private fun cardNumber() = "****" }
  14. Implement Interface open class Profile { fun info() = "name:

    ${name()}, cardNumber ${cardNumber()}" fun name() = "Saeed" private fun cardNumber() = "****" } interface Disposable { fun dispose() }
  15. Implement Interface val mock = spyk<Profile>(moreInterfaces = *arrayOf(Disposable::class)) every {

    (mock as Disposable).dispose() } answers { println(“disposing") } (mock as Disposable).dispose() // prints disposing
  16. Argument Matching // If you leave matcher, a fixed value

    automatically wrapped in eq matcher every { Math.sum(eq(5), 5) } returns 5 every { Math.sum(less(5), more(5)) } returns 0 every { Math.sum(any(), or(less(2), eq(2))) } returns 1 more, less, eq, or, any
  17. Capturing Arguments val slot = slot<Int>() mockkObject(Math) every { Math.sum(a

    = capture(slot), b = 2) } answers { println(slot.captured) 4 } Math.sum(1, 2) //prints 1 Math.sum(2,3) // prints nothing
  18. Capturing Arguments val list = mutableListOf<Int>() mockkObject(Math) every { Math.sum(a

    = capture(list), b = 2) } returns 4 every { Math.sum(a = capture(list), b = 3) } returns 4 Math.sum(1, 2) Math.sum(2,3) println(list) // prints [1, 2]
  19. Excepted Answer every { Math.sum(1, 2) } returns 5 returns:

    specify that matched call returns one specified value returnsMany: specify that matched call returns value from the list, returning each time next element every { Math.sum(1, 2) } returnsMany listOf(1, 2, 3)
  20. Excepted Answer answers { code }: specify that matched call

    answers with code block scoped with answer scope coAnswers { code }: specify that matched call answers with coroutine code block with answer scope
  21. Excepted Answer every { Math.sum(1, 2) } throws Exception("error") throws:

    specify that matched call throws an exception just Runs: specify that matched call is returning Unit (returns null) every { Math.printSum(1, 2) } just Runs
  22. Additional Answer (returnsMany) every { Math.sum(1, 2) } returns 3

    andThen 4 assertEquals(3, Math.sum(1, 2)) assertEquals(4, Math.sum(1, 2))
  23. Additional Answer (returnsMany) every { Math.sum(1, 2) } returns 3

    andThen 4 andThenThrows assertEquals(3, Math.sum(1, 2)) assertEquals(4, Math.sum(1, 2))
  24. Additional Answer (returnsMany) every { Math.sum(1, 2) } returns 3

    andThen 4 andThenThrows andThenThen { } assertEquals(3, Math.sum(1, 2)) assertEquals(4, Math.sum(1, 2))
  25. Additional Answer (returnsMany) every { Math.sum(1, 2) } returns 3

    andThen 4 andThenThrows andThenThen { } coAndThen { } assertEquals(3, Math.sum(1, 2)) assertEquals(4, Math.sum(1, 2))
  26. Additional Answer (returnsMany) every { Math.sum(1, 2) } returns 3

    andThen 4 andThenThrows andThenThen { } coAndThen { } answer { arg(1) + 4 } assertEquals(3, Math.sum(1, 2)) assertEquals(4, Math.sum(1, 2))
  27. Behavior Verification You can add different behaviors to verify DSL.

    Here are all possible DSLs for verification verify { } verifyAll { } verifySequence { } verifyOrder { }
  28. Behavior Verification Orders: verify(ordering = Ordering.ALL) { } • Unordered

    • Ordered • Sequence -> exact sequence happed • All -> without any interactions •
  29. Behavior Verification Check call count with atLeast, atMost or exactly

    or wasNot Called: verify(atLeast = 3) { } verify(atMost = 2) { } verify(exactly = 1) { } verify(atLeast = 3,atMost = 5) { } verify { torch.turnOn() wasNot Called }
  30. Behavior Verification To verify concurrent operations you can use: verify(timeout

    = 2000){ } To negate the conditions just enable inverse mode verify(inverse = true){ }
  31. Coroutines Support Just add co as a prefix coEvery coVerify

    coMatch coAssert coRun coAnswers coInvoke