lateinit属性模拟对象尚未初始化

时间:2020-06-02 10:50:22

标签: java unit-testing kotlin testing mocking

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

这似乎仅在我调用方法嘲笑(className)时才有效,但是由于我想在多个方法上使用模拟类,所以我不想在测试方法中继续重复相同的代码。

这是我的考试班:

{
   "id":"402-xxx-ee0",
   "status":200,
   "headers":{
      "Preference-Applied":"odata.track-changes",
      "Cache-Control":"no-cache",
      "OData-Version":"4.0",
      "Content-Type":"application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8"
   },
   "body":{
      "@odata.context":"https://graph.microsoft.com/v1.0/$metadata#groups",
      "@odata.nextLink":"https://graph.microsoft.com/v1.0/groups/delta?$skiptoken=5ZZ_<long_token>_OXWrtiE",
      "value":[

      ]
   }
}

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

我得到的错误:

{
   "id":"402-xxx-ee0",
   "status":200,
   "headers":{
      "Preference-Applied":"odata.track-changes",
      "Cache-Control":"no-cache",
      "OData-Version":"4.0",
      "Content-Type":"application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8"
   },
   "body":{
      "@odata.context":"https://graph.microsoft.com/v1.0/$metadata#groups",
      "@odata.nextLink":"https://graph.microsoft.com/v1.0/groups/delta?$skiptoken=5ZZ_<long_token>_DNF5rRE0",
      "value":[

      ]
   }
}

依赖项:

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

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:0)

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
) {

}