question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

lateinit property has not been initialized

See original GitHub issue

Hello,

I have the following class

@Path("/canceling")
class CancelResource {

  @Inject
  lateinit var cancelManager: CancelManager

  @POST
  @Path("{id}")
  fun cancelItem(@PathParam("id") id: String){
    cancelManager.addItem(id)
  }
}

A CancelManager which is an @ApplicationScoped class

@ApplicationScoped
class CancelManager {
  var ids = setOf<String>()

  fun addItem(id: String) {
    ids = ids.plus(id)
  }
}

To test the CancelResource I need to mock the CancelManager. I did the following:

Test :

internal class CancelResourceTest {
  @MockK
  lateinit var cancelManager: CancelManager

  @InjectMockKs
  lateinit var service: CancelResource

  @BeforeEach
  fun init() {
    MockKAnnotations.init(this)
    service = CancelResource()
  }

  @Test
  fun runTest() {
    val id = "dummy item"
    justRun { cancelManager.addItem(id) }

    service.cancelItem(id)

    verify { cancelManager.addItem(id) }
  }
}

Expected behavior: Correcly mocking the injection

Current behavior It gives the following error kotlin.UninitializedPropertyAccessException: lateinit property cancelManager has not been initialized

What’s wrong?


MockK version: 1.10.0 Kotlin version: 1.3.72 JUnit5: junit-jupiter: 5.7.0 and junit-platform: 1.7.0

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:7

github_iconTop GitHub Comments

2reactions
d35hcommented, Dec 31, 2020

I think that your problem is due to the fact that you’re trying to initialize CancelResource yourself, which should be the responsibility of the code you call in @BeforeEach block that is MockKAnnotations.init(this)

Delegate the initiation of mocks to the MockK framework, this code should work:

  @MockK
  lateinit var cancelManager: CancelManager

  @InjectMockKs
  lateinit var service: CancelResource

 @BeforeEach
  fun init() {
    MockKAnnotations.init(this)
  }

  @Test
  fun runTest() {
    val id = "dummy item"
    justRun { cancelManager.addItem(id) }

    service.cancelItem(id)

    verify { cancelManager.addItem(id) }
  }

Also, I would highly recommend you to go over the best practices for unit testing in Kotlin, in your case specifically the Create Mocks Once chapter, which suggests to get rid of vars and recreation of mocks for each tests and clear all mocks before a test instead: https://phauer.com/2018/best-practices-unit-testing-kotlin/#create-mocks-once

This being said, I would suggest to make a refactoring of your code (I hope you don’t mind) the following way, so that the ideas in the guide above can be applied:

open class CancelResourceTest {

    private val cancelManager: CancelManager = mockk(relaxed = true)

    private val service: CancelResource = CancelResource(cancelManager)

    @BeforeEach
    fun setUp() {
        clearAllMocks()
    }

    @Test
    fun runTest() {
        val id = "dummy item"
        cancelManager.addItem(id)

        service.cancelItem(id)

        verify { cancelManager.addItem(id) }
    }
}

@Path("/canceling")
class CancelResource(@Inject val cancelManager: CancelManager) {

    @POST
    @Path("{id}")
    fun cancelItem(@PathParam("id") id: String){
        cancelManager.addItem(id)
    }
}

@ApplicationScoped
class CancelManager {
    var ids = setOf<String>()

    fun addItem(id: String) {
        ids = ids.plus(id)
    }
}

I hope it helps

1reaction
Raibazcommented, Dec 4, 2020

I think your CancelManager should be annotated with @MockK, as it’s the class you’re mocking, and service should be annotated with @InjectMocks, as it’s the class you’re injecting mocks into.

And yes, you need to call MockKAnnotations.init(this) in your init function for the annotations to be initialized.

Hope this helps

Read more comments on GitHub >

github_iconTop Results From Across the Web

lateinit property data has not been initialized - Stack Overflow
The error happens because you never initialize it ( data = ... ), but you access it in { companyList-> displayData(data) } ....
Read more >
How to Check if a "lateinit" Variable Has Been Initialized or ...
The lateinit keyword is used when we are sure that the variable will be initialized before using it. If we don't initialize a...
Read more >
lateinit Property in Kotlin - Suneet Agrawal
Accessing a lateinit property before it has been initialized throws a special exception that clearly identifies the property being accessed and the fact...
Read more >
Initializing lazy and lateinit variables in Kotlin - LogRocket Blog
The lateinit keyword stands for “late initialization.” When used with a class property, the lateinit modifier keeps the property from being ...
Read more >
`lateinit property sessionParamsBuilder has not been ... - GitHub
SDK 32 works as expected. kotlin.UninitializedPropertyAccessException: lateinit property sessionParamsBuilder has not been initialized at app.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found