【问题标题】:lateinit property mock object has not been initializedlateinit 属性模拟对象尚未初始化
【发布时间】:2020-06-02 10:50:22
【问题描述】:

我正在尝试使用注释 @MockBean 初始化(通过模拟)两个对象

它似乎只有在我调用方法 mock(className) 时才有效,但由于我想在多个方法上使用模拟类,我不想在我的测试方法中重复相同的代码。

这是我的测试课:

@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))
    }
}

我不想使用 Spring Boot @Autowired 注释,因为我的 Spring 应用程序需要我不想加载的上下文。

我得到的错误:

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

依赖关系:

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"
}

【问题讨论】:

    标签: java unit-testing kotlin testing mocking


    【解决方案1】:

    我通过在 setUp() 中调用 initMocks 方法解决了这个问题

    @BeforeEach
        fun setUp() {
            MockitoAnnotations.initMocks(this)
            ....
        }
    

    【讨论】:

    • 不幸的是,我在使用此建议时收到此消息:“'initMocks(Any!): Unit' is deprecated. Deprecated in Java”
    【解决方案2】:

    MockitoJUnitRunner@Mock 注释一起使用。

    @MockBean 来自 Spring,因此您需要使用 @SpringRunner

    但是,您的示例似乎不需要 Spring,因此您可以切换到 @Mock

    @RunWith(MockitoJUnitRunner::class)
    class WordServiceTest {
    
        @Mock
        private lateinit var wordRepositoryMock: WordRepository
    
        @Mock
        private lateinit var wordMapperMock: WordMapper
    }
    

    如果你升级到 Junit5,你可以做进一步的改进(我只在 Junit5 中测试过)。构造函数参数是lateinit 的一个很好的替代方案:

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

    【讨论】:

    • 感谢您的回答。将鼠标悬停在 MockitoExtension::class 上会给我以下错误:Type mismatch. Required: KClass<out Runner!> Found: KClass<MockitoExtension> 您使用哪些依赖项?
    • 对不起,应该是@ExtendWith(MockitoExtension::class)
    • 是的,我知道了,但我现在收到以下错误:org.junit.platform.launcher.core.DefaultLauncher handleThrowable WARNING: TestEngine with ID 'junit-jupiter' failed to discover tests 查看我的 gradle 依赖项的更新帖子
    • 如果您现在尝试升级 junit,那么这将成为一个完全不同的问题;)@Test 注释位于不同的包中。注意不要将两者混合。我会尝试首先使其与现有版本一起使用(我的第一个示例)。没试过,但也许以下也可以? @RunWith(MockitoJUnitRunner::class) class WordServiceTest( @Mock val wordRepositoryMock: WordRepository, @Mock val wordMapperMock: WordMapper ) { }
    • 好吧,我都试过了,都给出了不同的错误。在第一个版本中,我遇到了错误:kotlin.UninitializedPropertyAccessException using @Test of package:import org.junit.jupiter.api.Test
    【解决方案3】:

    对于那些因为 initMocks(this) 已弃用而出现的函数,我注意到有一个更新的函数可以做到这一点:

    @BeforeEach
    fun setUp() {
        MockitoAnnotations.openMocks(this)
            ....
    }
    

    【讨论】:

    • 就是这样@spamove,感谢您的提醒。
    猜你喜欢
    • 2017-03-03
    • 1970-01-01
    • 2020-12-31
    • 2021-06-11
    • 2017-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多