UriがMockされていない
UnitTestでAndroid frameworkとして定義されているUriをそのまま用いると上記のようなErrorを発報します。構成はKotlin + JUnit5 + Androidです。
公式の理由と対処法は以下になります
Build local unit tests | Android Developers
localなJVMでUnit Testを実行できるようにAndroid Frameworkを使用するモジュールはAPI部のみを残して、実装を除去されてからUnit Testに渡されます。そのため、mockせずに使用することはできません。
回答としてはMockitoを用いてMockしてから利用します。
以下はsaveStateHandleからIntent, IntentからUriを取得して、そのUriに応じて挙動を変更するViewModelのテスト実装例です。
@ExtendWith(MockitoExtension::class) @kotlinx.coroutines.ExperimentalCoroutinesApi internal class ListSuggestionViewModelTest{ @Mock lateinit var savedStateHandle: SavedStateHandle @Mock lateinit var mockUri: Uri @Mock lateinit var mockIntent: Intent lateinit var viewModel: SomeTestViewModel @BeforeEach fun setUp() = runTest{ Mockito.`when`(mockUri.toString()).thenReturn("/test1/tes2/test3") Mockito.`when`(mockIntent.data).thenReturn(mockUri) Mockito.`when`(savedStateHandle.get<Intent>( "android-support-nav:controller:deepLinkIntent")).thenReturn(mockIntent) viewModel = SomeTestViewModel(savedStateHandle) }
私はJUnit5+Kotlinを使用するようにしているのでExtensionがJUnit4と少し異なります。build.gradleを以下にしてください。
//Local Unit Tests Dependency //junit4 // testImplementation 'junit:junit:4.13.2' testImplementation 'org.mockito:mockito-core:4.4.0' //junit5 testImplementation 'org.junit.vintage:junit-vintage-engine:5.8.2' testImplementation 'org.junit.jupiter:junit-jupiter:5.8.2' testImplementation 'org.mockito:mockito-junit-jupiter:4.4.0' //kotlin test extension testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.0'
JUnit4の方は以下を指定してください
@RunWith(MockitoJUnitRunner::class)
なお、これは@Mock annotationを楽に使用するためだけのannotationなので今回の問題の本質ではありません。