1

I am getting Null Pointer Exception whenever I try to verify method is called or not.

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
}

}

Presenter Class

 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()
}

}

These two methods need to be verified and updateUser() throws Null Pointer Exception

view.showOnCompleteCallSuccess() updateUser()

Logcat:

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)

FYI: I am using following Dependencies:

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'

4 Answers 4

2

You're not mocking the updateUser call.

You need to add something like the following into your test setup, depending on what updateUser is expected to return.

whenever(repository.updateUser(-1)).thenReturn(Completable.complete())
Sign up to request clarification or add additional context in comments.

5 Comments

Why do I need to mock call of method just to verify whether it is called or not? I am not performing any further operation for updateUser(). So, I guess it is not necessary to mock the updateUser() Call
Your presenter calls onCompleteCallClicked, this calls showOnCompleteCallSuccess which then calls updateUser. updateUser by default is null as it isn't mocked. If you're happy for a NullPointerException to be thrown in your test, i.e. you don't want to provide a value for updateUser you can use tell the test to expect an exception by using the expected parameter: @Test(expected = NullPointerException.class)
Adding @Test(expected = NullPointerException.class) throws same error as above.
If the NullPointerException isn't failing the test then you probably don't need to do anything, adding expected will tell the test to pass if the exception is thrown, it won't stop the exception from occurring in your presenter. The only way you can stop the NullPointerException in the test is to mock the updateUser method.
Ok Thanks. But I guess this is the issue with Mockito-Kotlin. I have posted the issue on Library too.
1

If you don't want to mock the output for the updateUser() you may implement a presenter interface class and verify if the presenterinterface function is invoked.

Step 1: Add a presenter interface class

interface INotesDialogPagePresenter {
   fun updateUser()
}

Step 2: Implement the interface class to your presenter

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()
}

Step 3: Update your test class (using mockito-kotlin)

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()
}

This way, you don't actually running the updateUser(), instead you'll just verify if the mocked interface object's fun being invoked. This prevents null pointer and incerease your test coverage.

2 Comments

So you basically want to say, I need to implement the Interface on the presenter and call the same method inside presenter itself i.e INotesDialogPagePresenter
That’s right. This way you can actually verify whether updateuser being invoked. The other solution here suggest to mock the response of updateuser when it is invoked, which is required to pass the test. But you can’t actually verify if the method being invoked.
0

Since you're mocking OrderSummaryRepository you'll have to mock out every method call that the consuming class i.e. in this case the NotesDialogPagePresenter calls on. So as Chris pointed out, you'll have to add a mock for updateUser()

repository.updateUser(anyInt()) doReturn any()

Comments

0

I had a similar issue and it turned out that methods that are to be mocked should be marked as open

Here is an example of code that will work:

class ToBeMocked {
    open fun myName() = "ToBeMocked"
}

class MyClass(val it: ToBeMocked)  {
   fun myName() = it.myName()
}

class MyClassTest {
    val myMock: ToBeMocked = mock()
    
    val sut = MyClass(myMock)

    @Test
    fun test() {
        whenever(myMock.myName()).thenReturn("Test")
        assertThat(sut.myName()).equalsTo("Test")
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.