首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >名为验证的Mockito Kotlin单元测试方法抛出空指针异常

名为验证的Mockito Kotlin单元测试方法抛出空指针异常
EN

Stack Overflow用户
提问于 2018-09-11 18:28:23
回答 4查看 4K关注 0票数 1

每当我尝试验证方法是否被调用时,我都会得到Null Pointer Exception

代码语言:javascript
运行
复制
class NotesDialogPagePresenterTest {

@Mock
private lateinit var repository: OrderSummaryRepository
@Mock
private lateinit var view: NotesDialogPageContract.View
@Mock
private lateinit var context: Context

private lateinit var presenter: NotesDialogPagePresenter
private val notes = "abcd"
private val remarks = "xyz"


@Before
fun setup() {
    MockitoAnnotations.initMocks(this)
    whenever(view.getContext()).thenReturn(context)
    this.presenter = NotesDialogPagePresenter(view, repository)
}

@Test
fun onCompleteCallClicked_successTest() {

    whenever(repository.updateOrderAfterCompleteCall(notes, remarks)).thenReturn(Completable.complete())

    val spyPresenter = Mockito.spy(presenter)
    spyPresenter.onCompleteCallClicked(notes, remarks)

    verify(view, times(1)).showOnCompleteCallSuccess()
    verify(spyPresenter, times(1)).updateUser()//Null Pointer Exception Here
}

}

演示者类

代码语言:javascript
运行
复制
 class NotesDialogPagePresenter @Inject constructor(var view: NotesDialogPageContract.View,
                                               var repository: OrderSummaryRepository)
: NotesDialogPageContract.Presenter {

private var disposable: Disposable? = null

override fun start() {
}

override fun onCompleteCallClicked(notes: String, remarks: String) {

    disposable = repository.updateOrderAfterCompleteCall(notes, remarks)
            .subscribe({
                view.showOnCompleteCallSuccess()
                updateUser() 
            }, {
                view.showError(it)
            })
}

@VisibleForTesting
internal fun updateUser() {
    disposable = repository.updateUser(-1)
            .subscribe({
                //NO-OP
            }, {
                //NO-OP
            })
}

override fun stop() {
    disposable?.dispose()
}

}

这两个方法需要验证,updateUser()抛出空指针异常

view.showOnCompleteCallSuccess() updateUser()

Logcat:

代码语言:javascript
运行
复制
java.lang.NullPointerException
    at com.rosia.bcp.ordersummary.notes.NotesDialogPagePresenter.updateUser$app_pgDebug(NotesDialogPagePresenter.kt:30)
    at com.rosia.bcp.ordersummary.notes.NotesDialogPagePresenter$onCompleteCallClicked$1.run(NotesDialogPagePresenter.kt:22)
    at io.reactivex.internal.observers.CallbackCompletableObserver.onComplete(CallbackCompletableObserver.java:54)
    at io.reactivex.internal.disposables.EmptyDisposable.complete(EmptyDisposable.java:68)
    at io.reactivex.internal.operators.completable.CompletableEmpty.subscribeActual(CompletableEmpty.java:27)
    at io.reactivex.Completable.subscribe(Completable.java:1794)
    at io.reactivex.Completable.subscribe(Completable.java:1860)
    at com.rosia.bcp.ordersummary.notes.NotesDialogPagePresenter.onCompleteCallClicked(NotesDialogPagePresenter.kt:20)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.rosia.bcp.ordersummary.notes.NotesDialogPagePresenter.onCompleteCallClicked(NotesDialogPagePresenter.kt:19)
    at com.rosia.bcp.ordersummary.notes.NotesDialogPagePresenterTest.onCompleteCallClicked_successTest(NotesDialogPagePresenterTest.kt:42)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runners.Suite.runChild(Suite.java:128)
    at org.junit.runners.Suite.runChild(Suite.java:27)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMainV2.main(AppMainV2.java:131)
Exception in thread "main" java.lang.NullPointerException
    at com.rosia.bcp.ordersummary.notes.NotesDialogPagePresenter.updateUser$app_pgDebug(NotesDialogPagePresenter.kt:30)
    at com.rosia.bcp.ordersummary.notes.NotesDialogPagePresenter$onCompleteCallClicked$1.run(NotesDialogPagePresenter.kt:22)
    at io.reactivex.internal.observers.CallbackCompletableObserver.onComplete(CallbackCompletableObserver.java:54)
    at io.reactivex.internal.disposables.EmptyDisposable.complete(EmptyDisposable.java:68)
    at io.reactivex.internal.operators.completable.CompletableEmpty.subscribeActual(CompletableEmpty.java:27)
    at io.reactivex.Completable.subscribe(Completable.java:1794)
    at io.reactivex.Completable.subscribe(Completable.java:1860)
    at com.rosia.bcp.ordersummary.notes.NotesDialogPagePresenter.onCompleteCallClicked(NotesDialogPagePresenter.kt:20)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.rosia.bcp.ordersummary.notes.NotesDialogPagePresenter.onCompleteCallClicked(NotesDialogPagePresenter.kt:19)
    at com.rosia.bcp.ordersummary.notes.NotesDialogPagePresenterTest.onCompleteCallClicked_successTest(NotesDialogPagePresenterTest.kt:42)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runners.Suite.runChild(Suite.java:128)
    at org.junit.runners.Suite.runChild(Suite.java:27)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMainV2.main(AppMainV2.java:131)

仅供参考:我使用以下依赖项:

代码语言:javascript
运行
复制
testImplementation 'org.mockito:mockito-core:2.19.0'
testImplementation 'com.squareup.retrofit2:retrofit-mock:2.3.0'
testImplementation 'org.mockito:mockito-inline:2.8.9'
testImplementation 'com.nhaarman:mockito-kotlin-kt1.1:1.6.0'
testImplementation 'junit:junit:4.12'
EN

Stack Overflow用户

发布于 2019-01-09 02:55:54

如果不想模拟updateUser()的输出,可以实现presenter接口类并验证是否调用了presenterinterface函数。

步骤1:添加presenter接口类

代码语言:javascript
运行
复制
interface INotesDialogPagePresenter {
   fun updateUser()
}

第2步:向演示者实现接口类

代码语言:javascript
运行
复制
class NotesDialogPagePresenter @Inject constructor(var view:NotesDialogPageContract.View,var repository: OrderSummaryRepository)
: NotesDialogPageContract.Presenter,INotesDialogPagePresenter {

private var disposable: Disposable? = null
var implNotesDialogPagePresenter :INotesDialogPagePresenter = this

override fun start() {
}

override fun onCompleteCallClicked(notes: String, remarks: String) {

    disposable = repository.updateOrderAfterCompleteCall(notes, remarks)
            .subscribe({
                view.showOnCompleteCallSuccess()
                implNotesDialogPagePresenter.updateUser() 
            }, {
                view.showError(it)
            })
}

override fun updateUser() {
    disposable = repository.updateUser(-1)
            .subscribe({
                //NO-OP
            }, {
                //NO-OP
            })
}

override fun stop() {
    disposable?.dispose()
}

步骤3:更新测试类(使用mockito-kotlin)

代码语言:javascript
运行
复制
class NotesDialogPagePresenterTest {

val view:NotesDialogPageContract.View= mock()
val repository:OrderSummaryRepository= mock()
val context:Context= mock()
val implNotesDialogPagePresenter :INotesDialogPagePresenter = mock()

private lateinit var presenter: NotesDialogPagePresenter
private val notes = "abcd"
private val remarks = "xyz"


@Before
fun setup() {
    whenever(view.getContext()).thenReturn(context)
    this.presenter = NotesDialogPagePresenter(view, repository)
    presenter.implNotesDialogPagePresenter = implNotesDialogPagePresenter 
}

@Test
fun onCompleteCallClicked_successTest() {

    whenever(repository.updateOrderAfterCompleteCall(notes, remarks)).thenReturn(Completable.complete())

    val spyPresenter = Mockito.spy(presenter)
    spyPresenter.onCompleteCallClicked(notes, remarks)

    verify(view, times(1)).showOnCompleteCallSuccess()
    verify(implNotesDialogPagePresenter , times(1)).updateUser()
}

这样,您实际上不会运行updateUser(),而只是验证被模拟的接口对象是否被调用。这可以防止空指针,并提高测试覆盖率。

票数 1
EN
查看全部 4 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52273867

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档