3

I would like to test a custom handler class which is starting a new Activity. I would like to test the Intent's Bundle if contains the pre defined parameters.

The test class:

@MockK
lateinit var activity: ActivityCalendar

@Before
fun setUp() {
    MockKAnnotations.init(this)
}

@Test
fun testActivityBundles() {
    val book = mockk<Book>()

    every { book.releaseDate } returns GregorianCalendar().apply { this.timeInMillis = 1423825586000 }
    every { activity.startActivity(any()) } just Runs

    val handler = ActivityHandler(activity)
    handler.startRequiredActivity(book)

    verify { activity.startActivity(
            withArg { intent ->
                val bundle = intent.extras!!
                val releaseDateTimeMillis = bundle.getLong("release_date", 0L)

                Assert.assertEquals(1423825586000, releaseDateTimeMillis)
            }
    ) }
}

The code above is crashing at line: val bundle = intent.extras!! but it shouldn't.

The class that I want to test:

class ActivityHandler(val activity: Activity) {
    fun startRequiredActivity(book: Book) {
        val intent = buildIntent(book)

        activity.startActivity(intent)
    }

    private fun buildIntent(book: Book): Intent {
        val extras = Bundle().apply {
            this.putLong("release_Date", book.releaseDate.timeInMillis)
        }

        return Intent(activity, ActivityBookDetails::class.java).apply {
            putExtras(extras)
        }
    }
}

data class Book(
        val releaseDate: GregorianCalendar
)

I debugged the code and I found out that function private fun buildIntent(book: Book): Intent is returning an "null" object (string "null" and not Java NULL).

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
Zbarcea Christian
  • 9,367
  • 22
  • 84
  • 137

2 Answers2

0

You are getting that weird Intent because you need an instrumented test for this, since an Intent is part of the core android library and needs to be run in a device. I assume you want to avoid testing on an emulator, so you could also use Roboelectric.

This has been discused in this thread.

0

This is an example of mocking by Mockk for Intent.

You need to mock hasExtra

every { intentMock.hasExtra("Your key") } returns true

Full Example:

 @Test
fun `Test`() {
    // Arrange
    val longValue = 1000L
    val enumValue = ModelEnum.MODEL1
    val intentMock = spyk<Intent>()
    every { intentMock.extras?.getLong("KEY_LONG_VALUE") } returns longValue
    every { intentMock.hasExtra(CheckoutRouter.RESULT_PAYMENT_TYPE) } returns true
    every { intentMock.getSerializableExtra("KEY_ENUM_VALUE") } returns enumValue

    // Action
    val a = A(intent = intentMock)
    val longValueResult = a.getLongValue()
    val enumValueResult =  a.getEnumValue()

    // Assert
    Assert.assertEquals(longValue, longValueResult)
    Assert.assertEquals(enumValue, enumValueResult)
}

class A (val intent: Intent){

    fun getLongValue():Long? {
        return intent.extras?.getLong("KEY_LONG_VALUE")
    }

    fun getEnumValue():ModelEnum? {
        return intent.getSerializableExtra("KEY_ENUM_VALUE") as? ModelEnum
    }
}

enum class ModelEnum{
    MODEL1,MODEL2
}
Rasoul Miri
  • 11,234
  • 1
  • 68
  • 78