スポンサーリンク

Method parse in android.net.Uri not mocked【Kotlin】【Unit Test】【Android】

スポンサーリンク

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なので今回の問題の本質ではありません。

タイトルとURLをコピーしました