2017-12-29 78 views
0

私は結果がIntent.ACTION_PICKで始まり、選択した連絡先を画面上に表示するボタン付きの単純なビューを持っています。 リファクタリングコードでMockitoのUnnecessaryStubbingExceptionをスローしないようにしました

  • 開接点活動

    • チェックandroid.permission.READ_CONTACTS場合が付与され
    • 選択接触をし、与えられた
    • チェック再び
    • 検索接触によるandroid.permission.READ_CONTACTSのためのアプリに戻って次のステップを取る必要があることを行うために、ウリ
    • show contact on screen

    私は、開いている連絡先の1つが取り消し権限を取り消し、選択した連絡先があるアプリに戻るときに、シナリオをテストします。期待される結果は、そのURIによって連絡先を見つける方法を呼び出すことではありません。

    残念ながら、現在の実装では、スロー:

    org.mockito.exceptions.misusing.UnnecessaryStubbingException:

    のために:

    whenever(interactor.getContact(any())).thenReturn(Maybe.just(Contact()).doOnSuccess { find = true }) 
    

    私はSilentStrictStubsを置き換えることができることを知っているが、私は現在のコードをリファクタリングしてより良い解決策を探しています。

    必要なすべてのクラスおよびテスト:

    class Contact 
    
    interface View { 
    
        val contactClicks: Observable<Any> 
    
        fun setContact(contact: Contact) 
    } 
    
    interface Interactor { 
    
        fun getContact(uri: String): Maybe<Contact> 
    } 
    
    interface Router { 
    
        fun goToContacts(): Maybe<String> 
    } 
    
    interface Permissioner { 
    
        fun requestReadContacts(): Single<Boolean> 
    } 
    
    class Presenter(
         private val view: View, 
         private val interactor: Interactor, 
         private val router: Router, 
         private val permissioner: Permissioner 
    ) { 
    
        private val disposables: CompositeDisposable = CompositeDisposable() 
    
        fun bindView() { 
         view.contactClicks 
           .flatMapSingle { permissioner.requestReadContacts() } //ask first time before opening contacts 
           .filter { it } 
           .flatMapMaybe { router.goToContacts() } 
           .flatMapMaybe { 
            permissioner.requestReadContacts() //ask second time before using ContentResolver 
              .filter { granted -> granted } 
              .flatMap { _ -> interactor.getContact(it) } 
           } 
           .subscribeBy { view.setContact(it) } 
           .addTo(disposables) 
        } 
    } 
    
    @RunWith(MockitoJUnitRunner.StrictStubs::class) 
    class PresenterTest { 
    
        @Mock 
        lateinit var view: View 
    
        @Mock 
        lateinit var router: Router 
    
        @Mock 
        lateinit var permissioner: Permissioner 
    
        @Mock 
        lateinit var interactor: Interactor 
    
        @InjectMocks 
        lateinit var presenter: Presenter 
    
        private val contactClickSubject = PublishSubject.create<Any>() 
    
        @Before 
        fun setUp() { 
         whenever(view.contactClicks).thenReturn(contactClickSubject) 
        } 
    
        @Test 
        fun shouldNotFindContactWhenReturnedWithUriAndPermissionNotGrantedSecondTime() { 
         var firstTimeAsk = true 
         whenever(permissioner.requestReadContacts()).thenReturn(Single.fromCallable { 
          if (firstTimeAsk) { 
           firstTimeAsk = false 
           [email protected] true 
          } else { 
           [email protected] false 
          } 
         }) 
         whenever(router.goToContacts()).thenReturn(Maybe.just("contact")) 
         var find = false 
         whenever(interactor.getContact(any())).thenReturn(Maybe.just(Contact()).doOnSuccess { find = true }) 
    
         presenter.bindView() 
         contactClickSubject.onNext(Any()) 
    
         assertFalse(find) 
        } 
    } 
    
  • 答えて

    2

    UnnecessaryStubbingExceptionは、あなたが何かをスタブが、実際にそれを使用していないことを意味します。そして、あなたのケースでは正しいです。interactor.getContactはテストでは呼び出されません。これは望ましい動作です。だから、それを突き刺すことに意味はない。

    最も簡単な解決策は、不必要な変数var find = falseとスタブを削除するだろう - あなたのテストの終了時にアサーションとそれらを置き換える:

    verify(interactor, never()).getContact(any()) 
    

    をこれはあなたの現在のソリューションと同等のが、ヘルパー変数を使用するよりも簡単です。

    関連する問題