I'm using Mockito to test my Kotlin code. It's a web app and I use spring to inject values into some fields.
For example, my class snippet looks something like this:
class MyComponent {
@Inject private lateinit var request: HttpServletRequest
@Inject private lateinit var database: Database
To mimic this in my unit test I use the @Mock
and @InjectMocks
annotations from Mockito. So my test looks something like this:
class MyComponentTest {
@Mock private lateinit var request: HttpServletRequest
@Mock private lateinit var database: Database
@InjectMocks private lateinit var sut: MyComponent
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
}
Which all works fine. However, I also have a lazy initialization block in my component like this:
val user: User by lazy {
database.findUser()
}
fun getUsername(): String {
return user.name
}
When my test calls myComponent.getUsername()
I would expect database.findUser()
to be called as it initializes user
but this doesn't happen.
If I put a breakpoint in the lazy block, it's never hit. Now I am assuming this is something to do with the way Mockito and @InjectMocks
must 'touch' user
but I don't really know. If I construct MyComponent
manually then the lazy block is executed - but this won't inject my mocks.
How can I ensure the lazy block is called correctly from my test?
UPDATE: After a week absence, attempting to reproduce this without any changes and I could not. Can't explain it.
I've tried to reproduce your problem and was not able to do so. This gist provides a working example.
However I would recommend revisiting the way you write tests. Consider following example:
class MyComponentTest {
val request = mock<HttpServletRequest>()
val database = mock<Database>()
val sut = MyComponent(request, database)
@Test
fun username() {
Mockito.`when`(database.findUser()).thenReturn(User("test"))
val username = sut.getUsername()
MatcherAssert.assertThat(username, Matchers.equalTo("test"))
}
}
Which in my opinion is easier to understand than the one in mentioned the gist.
In case you're interested the mock
helper function is a one liner:
inline fun <reified T : Any> mock() = Mockito.mock(T::class.java)
A full updated example can be found in this gist.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With