2017-03-13 13 views
1

だから、私は単純なテストを書いています。 問題は、テストランナーがモックコードの代わりに実際の 'Repository'クラスコードを実行していることです。 これについて例外が発生する理由は何ですか?Android。 Mockitoはモックの代わりに実際のオブジェクトを使用します

Testクラス

class SingInFacebookPresenterTest { 

    @Mock 
    private lateinit var view: SignInFacebookContract.View 

    @Mock 
    private lateinit var repository: Repository 

    @Captor 
    private lateinit var callback: ArgumentCaptor<RepositoryCallback.FacebookLoginImp> 

    private lateinit var presenter: SingInFacebookPresenter 

    private val serverToken = "token" 

    @Before 
    fun init() { 

     MockitoAnnotations.initMocks(this) 

     presenter = SingInFacebookPresenter(MockContext(), repository, view) 
    } 

    @Test 
    fun facebook_login_success() { 

     //Given 
     val token = "token" 
     val serverToken = "server token" 

     presenter.loginViaFacebook(token) 

     //When 
     verify(repository).loginViaFacebook(token, callback.capture()) 


     callback.value.onSuccess(serverToken) 

     //Then 
     verify(view).success(serverToken) 
    } 

プレゼンター

class SingInFacebookPresenter(var context: Context, var repository: Repository, var view: SignInFacebookContract.View): SignInFacebookContract.Presenter { 

    public override fun loginViaFacebook(token: String) { 
     repository.loginViaFacebook(token, object : RepositoryCallback.FacebookLoginImp { 
      override fun onSuccess(token: String) { 
       view.success(token) 
      } 

      override fun onFailure() { 
       view.onFailure() 
      } 

     }) 
    } 

リポジトリ

open class Repository(context: Context) { 

    init { 
     ApiHelper(context) 
    } 

    private var facebookLoginPresenterCallback: RepositoryCallback.FacebookLoginImp? = null 

    fun loginViaFacebook(token: String, facebookLoginPresenterCallback: RepositoryCallback.FacebookLoginImp?) { 
//  this.facebookLoginPresenterCallback = facebookLoginPresenterCallback 
     val signInResponse = ApiHelper.signInViaFacebook(token) 
//  signInResponse.enqueue(signInFacebookCallback) 
     signInResponse.enqueue(object : Callback<SignInResponse> { 
      override fun onResponse(call: Call<SignInResponse>?, response: Response<SignInResponse>?) { 
       if (response!!.isSuccessful) { 
        val token = response.body()?.token ?: return 
        facebookLoginPresenterCallback?.onSuccess(token) 
        return 
       } 
       facebookLoginPresenterCallback?.onFailure() 
      } 

      override fun onFailure(call: Call<SignInResponse>?, t: Throwable?) { 
       facebookLoginPresenterCallback?.onFailure() 
      } 
     }) 
    } 

    private val signInFacebookCallback = object : Callback<SignInResponse> { 
     override fun onResponse(call: Call<SignInResponse>?, response: Response<SignInResponse>?) { 
      if (response!!.isSuccessful) { 
       val token = response.body()?.token ?: return 
       facebookLoginPresenterCallback?.onSuccess(token) 
       return 
      } 
      facebookLoginPresenterCallback?.onFailure() 
     } 

     override fun onFailure(call: Call<SignInResponse>?, t: Throwable?) { 
      facebookLoginPresenterCallback?.onFailure() 
     } 
    } 
} 

例外:

Exception in thread "OkHttp Dispatcher" java.lang.NoSuchMethodError: okhttp3.internal.Platform.log(Ljava/lang/String;)V 
    at okhttp3.logging.HttpLoggingInterceptor$Logger$1.log(HttpLoggingInterceptor.java:109) 
    at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:157) 
    at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java:190) 
    at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:163) 
    at okhttp3.RealCall.access$100(RealCall.java:30) 
    at okhttp3.RealCall$AsyncCall.execute(RealCall.java:127) 
    at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
    at java.lang.Thread.run(Thread.java:745) 
Exception in thread "OkHttp Dispatcher" java.lang.NoSuchMethodError: okhttp3.internal.Platform.log(Ljava/lang/String;)V 
    at okhttp3.logging.HttpLoggingInterceptor$Logger$1.log(HttpLoggingInterceptor.java:109) 
    at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:157) 
    at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java:190) 
    at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:163) 
    at okhttp3.RealCall.access$100(RealCall.java:30) 
    at okhttp3.RealCall$AsyncCall.execute(RealCall.java:127) 
    at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
    at java.lang.Thread.run(Thread.java:745) 

org.mockito.exceptions.base.MockitoException: 
No argument value was captured! 
You might have forgotten to use argument.capture() in verify()... 
...or you used capture() in stubbing but stubbed method was not called. 
Be aware that it is recommended to use capture() only with verify() 

Examples of correct argument capturing: 
    ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class); 
    verify(mock).doSomething(argument.capture()); 
    assertEquals("John", argument.getValue().getName()); 

答えて

2

申し訳ありませんが、これは良いものです。ここに私が見つけたものがあります:

テストコードは問題ではありません、何かの理由でMockitoはRepositoryの実(?)インスタンスを作成します。または、少なくともどこかのメソッド呼び出しを傍受することができませんか?

はとにかく、ここでorg.mockito:mockito-core:2.7.11で問題を再現し、完全にストリップダウン例です:

open class Greeter { 
    fun hello() = "hello world" 
} 

class MockitoJavaExample { 

    @Test 
    fun test() { 
     val greeter: Greeter = mock() 
     println(greeter.hello()) // prints "hello world" which it shouldn't 
    } 

} 

私はこれが起こっているどのように伝えるためにMockitoの内部で十分に慣れていないんだけど、mockito-inlineの使用に切り替え異なるモッキング方法がこれを解決します。また、Kotlinの非openクラスを模擬することもできます。これは、あなたが拡張を目的にクラスを開かなくても、それらをテストするために必要なことかもしれません。このメソッドでは、クラスが開いているかどうかに関わらず、実際にはnullが返されるため、実際の実装は使用されません。

-coreの代わりにcompile 'org.mockito:mockito-inline:2.7.11'を使用してインラインバージョンのMockitoに切り替えることができます。

+0

ありがとうございました!私は一日中それを修正するために過ごしました:) –

+0

私はmockitoのために実際には同じことをしようとしましたが、それは動作しませんでした... –

+0

拡張ソリューションはいくつかのプロジェクト/他にはありません。なぜそれが薄れているのか分かりません。これは今までのところ信頼できるようです。 – zsmb13

関連する問題