Article Image
Article Image
read

Mocking is not elegant itself, though. Kotlin, on the other hand, can make anything look elegant.

Assume that we have a class named PushyNotification with one dependency, Notification. To do this, we interpret the implementation of PushyNotification and mock up the dependency.

class PushyNotificationTest {
  //  Dependencies
  lateinit var notification: Notification

  //  Mocks
  lateinit var pushyNotification: PushyNotification

  @BeforeEach
  fun setUp() {
    notification = `mock`(Notification::class.java)

    `when`(notification.token)
      .thenReturn(TOKEN)
    `when`(notification.expiration)
      .thenReturn(EXPIRATION_DATE)
    `when`(notification.qualityOfService)
      .thenReturn(QUALITY_OF_SERVICE)
    `when`(notification.collapseId)
      .thenReturn(COLLAPSE_ID)

    pushyNotification = PushyNotification(notification, TOPIC, false)
  }

  companion object {
    private val TOKEN = "token"

    private val EXPIRATION_DATE = Date.from(Instant.EPOCH)

    private val QUALITY_OF_SERVICE = QualityOfService.TRANSACTIONAL

    private val COLLAPSE_ID = "collapse id"
  }
}

We’re gonna implement two helper functions. Hence, we could create our mock as a one-liner, and we could avoid stating notification in each call to the when of Mockito.

Phase I: Kotlin-ish mock

We’re not able to use to good-old mock static method of Mockito, since it requires a Java class which will be available at runtime. So, this is impossible.

class PushyNotificationTest {
  ...

  //  Mocks
  val pushyNotification = `mock`(Notification::class.java)     //  compile-time error

  ...
}

Using reified generics of Kotlin, this can be fixed with the given implementation.

public inline fun <reified T: Any> mock() = Mockito.mock(T::class.java)

We can now declare the mock in a one-liner.

class PushyNotificationTest {
  ...

  //  Mocks
  val pushyNotification: PushyNotification = `mock`()

  ...
}

We’re explicitly declaring our type here, but I think it’s completely understandable. We could therefore understand the mocks’ actual type, in future.

Phase II: Contextual mockups

No matter what, I think, this looks ugly.

    ...
    `when`(notification.token)
      .thenReturn(TOKEN)
    `when`(notification.expiration)
      .thenReturn(EXPIRATION_DATE)
    `when`(notification.qualityOfService)
      .thenReturn(QUALITY_OF_SERVICE)
    `when`(notification.collapseId)
      .thenReturn(COLLAPSE_ID)
    ...

Thanks to contextual closures, we could bind another this to a block on a function.

public inline fun <T> T.apply(block: T.() -> Unit): T { block(); return this }

This is not implemented by me, but standard library. We could utilize this function to setup or mock objects.

class PushyNotificationTest {
  val notification: Notification = mock()

  lateinit var pushyNotification: PushyNotification

  @BeforeEach
  fun setUp() {
    notification.apply {
      `when`(token)
        .thenReturn(TOKEN)
      `when`(expiration)
        .thenReturn(EXPIRATION_DATE)
      `when`(qualityOfService)
        .thenReturn(QUALITY_OF_SERVICE)
      `when`(collapseId)
        .thenReturn(COLLAPSE_ID)
    }

    pushyNotification = PushyNotification(notification, TOPIC, false)
  }
  ...
}
Blog Logo

Buğra Ekuklu


Published

Image

The Nope Box

I say nope, nope, nope.

Back to Overview