Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

lateinit property mock object has not been initialized

I'm trying to initialize (by mocking) two objects with the annotation @MockBean

It seems only to work if i call the method mock(className), but since i want to use the mocked class on multiple methods i don't want to keep repeating the same code in my test methods.

This is my test class:

@RunWith(MockitoJUnitRunner::class)
class WordServiceTest {

    @MockBean
    lateinit var wordRepositoryMock: WordRepository

    @MockBean
    private lateinit var wordMapperMock: WordMapper

    @Test
    fun findAllTest() {
        // Error: lateinit property wordRepositoryMock has not been initialized
        val wordService = WordService(wordRepositoryMock, wordMapperMock)
        `when`(wordRepositoryMock.findAll()).thenReturn(listOf(
                WordEntity(UUID.randomUUID(), "xxx"),
                WordEntity(UUID.randomUUID(), "xxx")))
        assertEquals(2, wordService.findAll().size)
    }

    @Test
    fun wordExistsTest() {
        // This works fine
        val wordRepositoryMock = mock(WordRepository::class.java)
        val wordMapperMock = mock(WordMapper::class.java)
        val wordService = WordService(wordRepositoryMock, wordMapperMock)
        val word = "xxx"
        `when`(wordRepositoryMock.existsWordEntityByName(word)).thenReturn(true)
        assertEquals(true, wordService.wordExists(word))
    }
}

I don't want to use the Spring Boot @Autowired annotation because my spring application requires contexts which i don't want to load.

The error i'm getting:

lateinit property wordRepositoryMock has not been initialized
kotlin.UninitializedPropertyAccessException: lateinit property wordRepositoryMock has not been initialized

Dependencies:

dependencies {
    ...
    testImplementation("org.springframework.security:spring-security-test")
    testImplementation ('org.springframework.boot:spring-boot-starter-test') 
    testImplementation("org.junit.jupiter:junit-jupiter:5.6.2")
    testImplementation "org.junit.jupiter:junit-jupiter-params:5.5.2"
    testImplementation "org.junit.jupiter:junit-jupiter-api:5.6.2"
    testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:5.6.2"
    testImplementation("io.rest-assured:spring-mock-mvc:4.0.0")
    testImplementation("io.mockk:mockk:1.9.3")
    testImplementation "org.testcontainers:postgresql:1.11.3"
    testImplementation "org.springframework.kafka:spring-kafka-test:2.2.7.RELEASE"
    runtimeOnly('org.postgresql:postgresql')
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    testImplementation "org.mockito:mockito-junit-jupiter:3.3.3"
}
like image 412
J. Adam Avatar asked Jun 02 '20 10:06

J. Adam


People also ask

How do you initialize Lateinit property in Kotlin?

In order to create a "lateInit" variable, we just need to add the keyword "lateInit" as an access modifier of that variable. Following are a set of conditions that need to be followed in order to use "lateInit" in Kotlin. Use "lateInit" with a mutable variable. That means, we need to use "var" keyword with "lateInit".

How do I know if Lateinit property is initialized?

You can check if the lateinit variable has been initialized or not before using it with the help of isInitialized() method. This method will return true if the lateinit property has been initialized otherwise it will return false.

What is Lateinit in Kotlin?

The lateinit keyword allows you to avoid initializing a property when an object is constructed. If your property is referenced before being initialized, Kotlin throws an UninitializedPropertyAccessException , so be sure to initialize your property as soon as possible.


2 Answers

I solved this problem by calling initMocks method in setUp()

@BeforeEach
    fun setUp() {
        MockitoAnnotations.initMocks(this)
        ....
    }
like image 97
J. Adam Avatar answered Oct 29 '22 04:10

J. Adam


MockitoJUnitRunner works with the @Mock annotation.

@MockBean is coming from Spring so you need to use the @SpringRunner.

However, it looks like your examples don't need Spring, so you can switch to @Mock:

@RunWith(MockitoJUnitRunner::class)
class WordServiceTest {

    @Mock
    private lateinit var wordRepositoryMock: WordRepository

    @Mock
    private lateinit var wordMapperMock: WordMapper
}

There's a further improvement you could make if you upgraded to Junit5 (I only tested it in Junit5). Constructor arguments are a good alternative to lateinit:

@ExtendWith(MockitoExtension::class)
class WordServiceTest(
    @Mock val wordRepositoryMock: WordRepository,
    @Mock val wordMapperMock: WordMapper
) {

}
like image 25
Jakub Zalas Avatar answered Oct 29 '22 05:10

Jakub Zalas