質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
JUnit

JUnitは、Javaで開発されたプログラムのユニットテストを行うためのアプリケーションフレームワークです。簡単にプログラムのユニットテストを自動化することができ、結果もわかりやすく表示されるため効率的に開発時間を短縮できます。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

Q&A

解決済

1回答

3255閲覧

Android Studio kotlinでJunitテスト、Argument(s) are different! Wantedを解決できない

kotatsu828

総合スコア6

JUnit

JUnitは、Javaで開発されたプログラムのユニットテストを行うためのアプリケーションフレームワークです。簡単にプログラムのユニットテストを自動化することができ、結果もわかりやすく表示されるため効率的に開発時間を短縮できます。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

0グッド

0クリップ

投稿2020/04/12 06:43

編集2020/04/12 06:54

#前提・実現したいこと

Androidアプリ開発でkotlinでJunitテストを取り入れてみました。
下記のfun autoLoginTest()のverifyはpassすると思っていましたが、Coroutine周りで怒られているようです。
error内容について調べましたが、Coroutineについての理解が浅く解決できません。

なぜエラーになるのか、どうしたら解決できるのか教えていただきたいです。
よろしくお願いします。

###前提
presenterのautoLogin()についてのテストです
コード中のuserRepository.getUserProfile()はsuspend functionです。

architecture sampleのtodoアプリのtodo-mvp-coroutineを参考にしています
https://github.com/dmytrodanylyk/android-architecture/tree/todo-mvp-kotlin-coroutines

#発生している問題・エラーメッセージ

Argument(s) are different! Wanted: userRepository.getUserProfile( Continuation at com.example.gotcha2.autoLogin.AutoLoginPresenterTest$testAutoLogin$1.invokeSuspend(AutoLoginPresenterTest.kt:68) ); -> at com.example.gotcha2.data.source.repository.UserRepository.getUserProfile(UserRepository.kt:16) Actual invocation has different arguments: userRepository.getUserProfile( Continuation at com.example.gotcha2.autoLogin.AutoLoginPresenter$autoLogin$1.invokeSuspend(AutoLoginPresenter.kt:33) ); -> at com.example.gotcha2.autoLogin.AutoLoginPresenter$autoLogin$1.invokeSuspend(AutoLoginPresenter.kt:33) Comparison Failure: <Click to see difference>

#該当のソースコード
##コード
AutoLoginPresenter

kotlin

1class AutoLoginPresenter(private val userRepository: UserRepository, 2 private val autoLoginView: AutoLoginContract.View, 3 private val uiContext: CoroutineContext = 4Dispatchers.Main 5 ) 6 : AutoLoginContract.Presenter{ 7 init { 8 autoLoginView.presenter = this 9 } 10 11 override fun start() { 12 autoLogin() 13 } 14 15 private fun autoLogin() = launchSilent(uiContext){ 16 17 //realmからprofileを取ってきて、そのあとログイン処理を行う 18 19 val profileResult = userRepository.getUserProfile() 20 21// println(profileResult.toString()) 22 if (profileResult is Result.Success){ 23 24 val loginResult = userRepository.login(profileResult.data) 25 if(loginResult is Result.Success<UserProfile>){ 26 autoLoginView.transitionOriginFriend() 27 }else{ 28 autoLoginView.transitionLogin() 29 } 30 } 31 //アカウントがLocalに存在しない 32 else if(profileResult is Result.Error){ 33 autoLoginView.transitionCreateAccount() 34 }else{ 35 36 } 37 } 38}

CoroutineExt.kt

kotlin

1fun launchSilent( 2 context: CoroutineContext = Dispatchers.Main, 3 start: CoroutineStart = CoroutineStart.DEFAULT, 4 block: suspend CoroutineScope.() -> Unit 5) { 6 GlobalScope.launch(context, start, block) 7} 8 9/** 10 * Equivalent to [runBlocking] but return [Unit] instead of [T]. 11 * 12 * Mainly for usage when you want to lift [runBlocking] to return. Example: 13 * 14 * ``` 15 * override fun loadData() = runBlockingSilent { 16 * // code 17 * } 18 * ``` 19 */ 20fun <T> runBlockingSilent(context: CoroutineContext = EmptyCoroutineContext, block: suspend CoroutineScope.() -> T) { 21 runBlocking(context, block) 22}

##テストコード

kotlin

1 2class AutoLoginPresenterTest { 3 4 @Mock private lateinit var userRepository: UserRepository 5 6 @Mock private lateinit var autoLoginView: AutoLoginContract.View 7 8 private lateinit var autoLoginPresenter: AutoLoginPresenter 9 10 private val EMAIL = "email" 11 12 private val PASSWORD = "password" 13 14 private val UID = "uid" 15 16 private val CREATED_AT: Timestamp = Timestamp.now() 17 18 private val USER_PROFILE = UserProfile(UID,CREATED_AT,EMAIL,PASSWORD) 19 20 21 @Before 22 fun setup(){ 23// Dispatchers.setMain(Dispatchers.Unconfined) 24 MockitoAnnotations.initMocks(this) 25 26 27 `when`(autoLoginView.isActive).thenReturn(true) 28 } 29 30 31 @Test 32 fun testAutoLogin() = runBlockingSilent { 33 `when`(userRepository.getUserProfile()).thenReturn(Result.Success(USER_PROFILE)) 34 `when`(userRepository.login(USER_PROFILE)).thenReturn(Result.Success(USER_PROFILE)) 35 36 autoLoginPresenter = AutoLoginPresenter(userRepository, autoLoginView, Unconfined).apply { start() } 37 //今回の問題 38 verify(userRepository).getUserProfile() 39 40 } 41 42}

#試したこと
#使っているツールのバージョンなど補足情報

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kakajika

2020/04/12 15:32

coroutinesやmockitoのバージョンはいくつですか?
kotatsu828

2020/04/13 10:40

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.4' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.4' testImplementation "com.nhaarman:mockito-kotlin:1.5.0" testImplementation 'org.mockito:mockito-inline:2.21.0' testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.2.1' androidTestImplementation("org.mockito:mockito-android:2.24.5") 以上です。よろしくお願いします。
guest

回答1

0

ベストアンサー

mockitoのバージョンが古いために、coroutines@1.0.0以降のパッケージ名の変更への対応が適用されていないのだと思います。こちらのPRによればmockito@2.23.0のリリースに含まれているとのことなので、それ以上のバージョンに上げて試してみてください。


一応エラーの原因を解説しておくと、

suspend関数は実際には引数の最後にContinuationを追加した通常の関数に変換されるのですが、このContinuationの値はコルーチン毎に別のものとなります。ご質問のコードの場合はautoLogin()の中でlaunchを呼んで新たなコルーチンを生成しているので、その中で呼び出されたgetUserProfile()にはlaunchの外とは別のContinuationが渡されるわけです。これにより引数のContinuationが一致しないよ!というエラーが出ています。
これを避けるために、mockitoでは引数の最後にContinuationがある関数(つまりsuspend関数)についてはContinuationを除外した引数を比較するように実装されています。

投稿2020/04/13 11:32

編集2020/04/13 11:35
kakajika

総合スコア3131

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kotatsu828

2020/04/13 13:46

passしました!丁寧な解説もつけてくださり、ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問