Java 重构代码以避免抛出Mockito';这是不必要的例外
我有一个带有按钮的简单视图,该按钮启动Java 重构代码以避免抛出Mockito';这是不必要的例外,java,android,kotlin,mockito,rx-java,Java,Android,Kotlin,Mockito,Rx Java,我有一个带有按钮的简单视图,该按钮启动意图。操作\u选择作为结果,然后在屏幕上显示所选联系人。为此,必须采取以下步骤: 检查是否授予了android.permission.READ\u CONTACTS 开放式接触活动 选择联系人并返回应用程序 检查android。权限。再次阅读联系人 通过给定uri查找联系人 在屏幕上显示联系人 我想测试一个场景,当一个打开的联系人超过撤销权限,并返回到应用程序与选定的联系人。预期结果不是调用通过其uri查找联系人的方法 不幸的是,当前的实现抛出: org
意图。操作\u选择作为结果,然后在屏幕上显示所选联系人。为此,必须采取以下步骤:
- 检查是否授予了android.permission.READ\u CONTACTS
开放式接触活动
选择联系人并返回应用程序
检查android。权限。再次阅读联系人
通过给定uri查找联系人
在屏幕上显示联系人
我想测试一个场景,当一个打开的联系人超过撤销权限,并返回到应用程序与选定的联系人。预期结果不是调用通过其uri查找联系人的方法
不幸的是,当前的实现抛出:
org.mockito.exceptions.misusing.UnnecessaryStubbingException:
用于:
我知道我可以用Silent
替换StrictStubs
,但我正在寻找重构当前代码的更好解决方案
所有必要的课程和测试:
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
return@fromCallable true
} else {
return@fromCallable 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)
}
}
class联系人
界面视图{
val:可观察到
乐趣设置联系人(联系人:联系人)
}
接口交互器{
fun-getContact(uri:String):也许吧
}
接口路由器{
有趣的goToContacts():也许吧
}
接口许可证{
fun requestReadContacts():单个
}
课堂演示者(
私有val视图:视图,
私有val交互器:交互器,
专用val路由器:,
私人val许可证持有人:许可证持有人
) {
私有val一次性用品:CompositeDisposable=CompositeDisposable()
fun bindView(){
查看联系人点击
.flatMapSingle{Permission.requestReadContacts()}//在打开联系人之前第一次询问
.filter{it}
.flatmap可能{router.goToContacts()}
A.也许吧{
permissioner.requestReadContacts()//在使用ContentResolver之前第二次询问
.filter{已授予->已授予}
.flatMap{{->interactior.getContact(it)}
}
.subscribeBy{view.setContact(it)}
.addTo(一次性用品)
}
}
@RunWith(MockitoJUnitRunner.StrictStubs::class)
课堂演示者测试{
@嘲弄
lateinit变量视图:视图
@嘲弄
lateinit var路由器:路由器
@嘲弄
lateinit var许可证持有人:许可证持有人
@嘲弄
lateinit变量交互器:交互器
@注射模拟
lateinit var演示者:演示者
private val contactClickSubject=PublishSubject.create()
@以前
趣味设置(){
无论何时(查看。联系人单击)。然后返回(联系人单击主题)
}
@试验
当使用Uri返回且许可证未授予第二次()时,不应找到乐趣{
var firstTimeAsk=true
无论何时(permissioner.requestReadContacts())。然后返回(Single.fromCallable{
如果(首次提问){
firstTimeAsk=false
return@fromCallable真的
}否则{
return@fromCallable假的
}
})
无论何时(router.goToContacts())。然后返回(可能是.just(“contact”))
var find=false
无论何时(interactior.getContact(any()).thenReturn(Maybe.just(Contact()).doOnSuccess{find=true})
presenter.bindView()文件
contactClickSubject.onNext(任意())
assertFalse(查找)
}
}
不必要的存根异常
表示您正在存根某些内容,但实际上并未使用它。这是正确的,在您的情况下,interactitor.getContact
不应该在测试中被调用-这是期望的行为。因此,没有必要对其进行删节
最简单的解决方案是删除不必要的变量var find=false
并存根-在测试结束时用断言替换它们:
verify(interactor, never()).getContact(any())
这相当于您当前的解决方案,但比使用帮助器变量更简单。不必要的stubbingException
表示您正在stubbing某些内容,但并未真正使用它。这是正确的,在您的情况下,interactitor.getContact
不应该在测试中被调用-这是期望的行为。因此,没有必要对其进行删节
最简单的解决方案是删除不必要的变量var find=false
并存根-在测试结束时用断言替换它们:
verify(interactor, never()).getContact(any())
这相当于您当前的解决方案,但比使用辅助变量更简单