我正在向使用RxJava 2的类编写单元测试。当在观察者上调用onNext()时,我希望printV()
被调用一次。在代码中,一次调用成功。但是,当我在单元测试中测试此片段时,该方法被调用3次。
问题在于如何使它在测试中仅被调用一次,以及为什么在测试中它被调用比实际代码中多次。
onMenuLoaded()
从日志中可以看到该方法的调用位置
//in ViewModel class, under testing
fun loadMenu() {
menuInteractorImpl.getMainMenu()?.subscribeOn(Schedulers.io())?.observeOn(AndroidSchedulers.mainThread())?.subscribe(
{ items ->
onMenuLoaded(items)
},
{ error ->
//error handling logic
}
)?.let { compositeDisposables.add(it) }
}
//Test
@RunWith(PowerMockRunner::class)
@PowerMockRunnerDelegate(MockitoJUnitRunner::class)
@PrepareForTest(MenuInteractorImpl::class, MainMenuViewModel::class)
class MainMenuViewModelTest {
@get:Rule
var instantExecutorRule = InstantTaskExecutorRule()
companion object {
@ClassRule
@JvmField
val schedulers = RxImmediateSchedulerRule()
}
@Before
fun setUp() {
doNothing().`when`(viewModel).startTimerToScrollViewPager()
}
@Test
fun `test load menu calls onMenuLoaded when success`() {
val mockObservable = Observable.just(mockDataFactory.mockMenu).doOnNext {
viewModel.onMenuLoaded(it)
}.subscribeOn(Schedulers.newThread())
Mockito.`when`(menuInteractorImpl.getMainMenu()).thenReturn(mockObservable)
viewModel.loadMenu() //this method is called 3 times
Mockito.verify(viewModel, times(1)).onMenuLoaded(any())
}
解决方案:
问题在于意外地将PowerMockito viewModel.loadMenu();
-> at com.example.mainmenu.MainMenuViewModelTest.test load menu calls onMenuLoaded when success(MainMenuViewModelTest.kt:88)
viewModel.loadMenu();
-> at org.powermock.core.MockGateway.doMethodCall(MockGateway.java:182)
viewModel.loadMenu();
-> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
和Mockito spy
组合在一起。导入Mockito的mock
时,问题已解决。
答案 0 :(得分:0)
您的真实代码正在onMenuLoaded(items)
中调用onNext
,然后您的模拟可观察对象还从doOnNext
对其进行调用。
您需要删除可观察到的模拟中的doOnNext
部分:
@Test
fun `test load menu calls onMenuLoaded when success`() {
val mockObservable = Observable.just(mockDataFactory.mockMenu)
.subscribeOn(Schedulers.newThread())
Mockito.`when`(menuInteractorImpl.getMainMenu()).thenReturn(mockObservable)
viewModel.loadMenu() //this method is called 3 times
Mockito.verify(viewModel, times(1)).onMenuLoaded(any())
}
答案 1 :(得分:0)
问题出在意外地将PowerMockito间谍和Mockito模拟结合在一起。导入Mockito的间谍时,此问题已解决。
编辑:
我再次遇到相同的问题,解决方案则不同。看起来是将PowerMockito和Mockito组合在一起是同样的原因。这次我通过添加一个doNothing
块
doNothing().`when`(viewModel).myCall(true)