JUnit 5 注释 - 不适用于 LiveData/参数化测试
JUnit 5 Annotations - Not Working with LiveData / Parameterized Tests
概览
预期行为
使用mockObject
函数implementation with annotation syntax initialization for JUnit 5 as outlined in the documentation and Medium post by @oleksiyp替换模拟对象初始化。
当前行为
有问题的测试是 parameterized test as outlined by @phauer for JUnit 5 which seems to conflict with @ExtendWith(MockKExtension::class)
. In order to implement tests with LiveData the test must run synchronously in the local unit test using this InstantExecutorExtension
designed by @JeroenMols。
模拟对象初始化与 mockObject
函数一起按预期工作,但使用注释 @MockK
.
失败
错误
警告message/Build失败:
Repeatable annotations with non-SOURCE retention are not yet supported.
实施
mockObject
函数实现(按预期工作)
@ExtendWith(InstantExecutorExtension::class)
class NavigateContentTests {
private val mainThreadSurrogate = newSingleThreadContext("UI thread")
private val contentViewModel = ContentViewModel()
// This is the stream of tests to run in the Parameterized test below.
private fun NavigateContent() = Stream.of(
NavigateContentTest(
isRealtime = false,
feedType = MAIN,
timeframe = DAY,
mockFeedList = mockDbContentListForDay,
mockContent = mockArticleContent),
...)
@BeforeAll
fun beforeAll() { mockkObject(ContentRepository) }
@AfterAll
fun afterAll() { unmockkAll() // Re-assigns transformation of object to original state prior to mock. }
@BeforeEach
fun beforeEach() { Dispatchers.setMain(mainThreadSurrogate) }
@AfterEach
fun afterEach() {
Dispatchers.resetMain() // Reset main dispatcher to the original Main dispatcher.
mainThreadSurrogate.close()
}
@ParameterizedTest
@MethodSource("NavigateContent")
fun `Navigate Content`(test: NavigateContentTest) = runBlocking {
every { ContentRepository.getMainFeedList(test.isRealtime, any()) } returns mockGetMainFeedList(
test.mockFeedList, CONTENT)
every {
ContentRepository.queryLabeledContentList(test.feedType)
} returns mockQueryMainContentList(test.mockFeedList)
every { ContentRepository.getContent(test.mockContent.id) } returns mockGetContent(test)
// Tests here...
// Verification here...
}
}
注解语法初始化(由于两个扩展@ExtendWith
而无法正常工作)
@ExtendWith(InstantExecutorExtension::class)
@ExtendWith(MockKExtension::class)
class NavigateContentTests {
// This object should be mocked.
@MockK
lateinit var contentRepository: ContentRepository
private val mainThreadSurrogate = newSingleThreadContext("UI thread")
private val contentViewModel = ContentViewModel()
// This is the stream of tests to run in the Parameterized test below.
private fun NavigateContent() = Stream.of(
NavigateContentTest(
isRealtime = false,
feedType = MAIN,
timeframe = DAY,
mockFeedList = mockDbContentListForDay,
mockContent = mockArticleContent),
...)
@BeforeAll
fun beforeAll() { MockKAnnotations.init(this, relaxUnitFun = true) // turn relaxUnitFun on for }
@AfterAll
fun afterAll() { unmockkAll() // Re-assigns transformation of object to original state prior to mock. }
@BeforeEach
fun beforeEach() { Dispatchers.setMain(mainThreadSurrogate) }
@AfterEach
fun afterEach() {
Dispatchers.resetMain() // Reset main dispatcher to the original Main dispatcher.
mainThreadSurrogate.close()
}
@ParameterizedTest
@MethodSource("NavigateContent")
fun `Navigate Content`(test: NavigateContentTest) = runBlocking {
every { contentRepository.getMainFeedList(test.isRealtime, any()) } returns mockGetMainFeedList(
test.mockFeedList, CONTENT)
every {
contentRepository.queryLabeledContentList(test.feedType)
} returns mockQueryMainContentList(test.mockFeedList)
every { contentRepository.getContent(test.mockContent.id) } returns mockGetContent(test)
// Tests here...
// Verification here...
}
}
环境
- MockK 版本:1.9.3
- OS: Mac 10.14.6
- Kotlin 版本:1.3.50
- JDK版本:12.0.1
- JUnit 版本:5.5.1
- 测试类型:单元测试
根据此GitHub issue, as documented by the MockK creator, @oleksiy,这是一个错误。
一旦我看到错误已解决,我将更新此 post。
概览
预期行为
使用mockObject
函数implementation with annotation syntax initialization for JUnit 5 as outlined in the documentation and Medium post by @oleksiyp替换模拟对象初始化。
当前行为
有问题的测试是 parameterized test as outlined by @phauer for JUnit 5 which seems to conflict with @ExtendWith(MockKExtension::class)
. In order to implement tests with LiveData the test must run synchronously in the local unit test using this InstantExecutorExtension
designed by @JeroenMols。
模拟对象初始化与 mockObject
函数一起按预期工作,但使用注释 @MockK
.
错误
警告message/Build失败:
Repeatable annotations with non-SOURCE retention are not yet supported.
实施
mockObject
函数实现(按预期工作)
@ExtendWith(InstantExecutorExtension::class)
class NavigateContentTests {
private val mainThreadSurrogate = newSingleThreadContext("UI thread")
private val contentViewModel = ContentViewModel()
// This is the stream of tests to run in the Parameterized test below.
private fun NavigateContent() = Stream.of(
NavigateContentTest(
isRealtime = false,
feedType = MAIN,
timeframe = DAY,
mockFeedList = mockDbContentListForDay,
mockContent = mockArticleContent),
...)
@BeforeAll
fun beforeAll() { mockkObject(ContentRepository) }
@AfterAll
fun afterAll() { unmockkAll() // Re-assigns transformation of object to original state prior to mock. }
@BeforeEach
fun beforeEach() { Dispatchers.setMain(mainThreadSurrogate) }
@AfterEach
fun afterEach() {
Dispatchers.resetMain() // Reset main dispatcher to the original Main dispatcher.
mainThreadSurrogate.close()
}
@ParameterizedTest
@MethodSource("NavigateContent")
fun `Navigate Content`(test: NavigateContentTest) = runBlocking {
every { ContentRepository.getMainFeedList(test.isRealtime, any()) } returns mockGetMainFeedList(
test.mockFeedList, CONTENT)
every {
ContentRepository.queryLabeledContentList(test.feedType)
} returns mockQueryMainContentList(test.mockFeedList)
every { ContentRepository.getContent(test.mockContent.id) } returns mockGetContent(test)
// Tests here...
// Verification here...
}
}
注解语法初始化(由于两个扩展@ExtendWith
而无法正常工作)
@ExtendWith(InstantExecutorExtension::class)
@ExtendWith(MockKExtension::class)
class NavigateContentTests {
// This object should be mocked.
@MockK
lateinit var contentRepository: ContentRepository
private val mainThreadSurrogate = newSingleThreadContext("UI thread")
private val contentViewModel = ContentViewModel()
// This is the stream of tests to run in the Parameterized test below.
private fun NavigateContent() = Stream.of(
NavigateContentTest(
isRealtime = false,
feedType = MAIN,
timeframe = DAY,
mockFeedList = mockDbContentListForDay,
mockContent = mockArticleContent),
...)
@BeforeAll
fun beforeAll() { MockKAnnotations.init(this, relaxUnitFun = true) // turn relaxUnitFun on for }
@AfterAll
fun afterAll() { unmockkAll() // Re-assigns transformation of object to original state prior to mock. }
@BeforeEach
fun beforeEach() { Dispatchers.setMain(mainThreadSurrogate) }
@AfterEach
fun afterEach() {
Dispatchers.resetMain() // Reset main dispatcher to the original Main dispatcher.
mainThreadSurrogate.close()
}
@ParameterizedTest
@MethodSource("NavigateContent")
fun `Navigate Content`(test: NavigateContentTest) = runBlocking {
every { contentRepository.getMainFeedList(test.isRealtime, any()) } returns mockGetMainFeedList(
test.mockFeedList, CONTENT)
every {
contentRepository.queryLabeledContentList(test.feedType)
} returns mockQueryMainContentList(test.mockFeedList)
every { contentRepository.getContent(test.mockContent.id) } returns mockGetContent(test)
// Tests here...
// Verification here...
}
}
环境
- MockK 版本:1.9.3
- OS: Mac 10.14.6
- Kotlin 版本:1.3.50
- JDK版本:12.0.1
- JUnit 版本:5.5.1
- 测试类型:单元测试
根据此GitHub issue, as documented by the MockK creator, @oleksiy,这是一个错误。
一旦我看到错误已解决,我将更新此 post。