概要
予想される行動
@oleksiypによるドキュメントおよびMedium の投稿mockObject
で概説されているように、関数実装を使用したモック オブジェクトの初期化を JUnit 5 の注釈構文の初期化に置き換えます。
現在の動作
問題のテストは、JUnit 5 の@phauerによって概説されているパラメーター化されたテストであり、 . LiveData を使用してテストを実装するには、 @JeroenMolsによって設計されたthisを使用して、ローカル ユニット テストでテストを同期的に実行する必要があります。@ExtendWith(MockKExtension::class)
InstantExecutorExtension
モック オブジェクトの初期化は関数で期待どおりにmockObject
機能しますが、注釈を使用すると失敗します@MockK
。
エラー
警告メッセージ/ビルド失敗:
非 SOURCE 保持の反復可能なアノテーションはまだサポートされていません。
実装
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...
}
}
注釈構文の初期化 (拡張機能が 2 つあるため機能しません@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...
}
}
環境
- モックKバージョン: 1.9.3
- OS: マック 10.14.6
- コトリンのバージョン: 1.3.50
- JDK バージョン: 12.0.1
- JUnit バージョン: 5.5.1
- テストの種類: 単体テスト