2017-12-29 3 views
0

결과에 대한 Intent.ACTION_PICK을 시작하고 화면에 선택한 연락처를 표시하는 버튼이있는 간단한보기가 있습니다. 리팩터링 코드가 Mockito의 UnnecessaryStubbingException을 throw하지 않도록

  • 열린 접점 활동

    • 체크 android.permission.READ_CONTACTS 경우가 부여됩니다
    • 연락처 선택을 주어진
    • 체크 다시
    • 찾기 접촉에 의해 android.permission.READ_CONTACTS을위한 응용 프로그램으로 돌아가 : 다음 단계를 수행해야 할합니다 uri
    • 화면에 연락처 표시

    하나의 열린 연락처가 권한 취소보다 많은 시나리오를 테스트하고 선택한 연락처로 돌아갈 때 테스트하고 싶습니다. 예상 결과는 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()) 
    

    .