0

Good afternoon, I have a nullpointer exception when stubbing

package com.micheladrien.android.fresquerappel

import android.app.Application
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import com.micheladrien.fresquerappel.R
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock    
import org.mockito.Mockito.`when`
import org.mockito.Mockito.mock
import org.mockito.junit.MockitoJUnitRunner


@RunWith(MockitoJUnitRunner::class)
class MainViewModelTest {

  @Rule
  @JvmField
  var instantTaskExecutorRule = InstantTaskExecutorRule()    

  @Mock
  val applicationMock: Application = mock(Application::class.java)
 
  @Before
  fun setUpTaskDetailViewModel() {
        `when`(applicationMock.getString(R.string.collage_climat)).thenReturn("Climat")
    }
    }

edit : I need to stub the function when(applicationMock.getString(R.string.collage_climat)).thenReturn("Climat") because my viewmodel will get strings from context.

According to this blog post : https://codepills.com/2018/05/10/3-basic-mistakes-for-nullpointerexception-when-mock/ I should replace when thenreturn by when then (answer) which if it's true, why ?

I have already Tested : Changing R.id value to a brut number. => Same error Mocking the file inside the before and using lateinit for the declaration at @Mock => same error

Unlike previous question thread Mockito - NullpointerException when stubbing Method I am directly stubbing the method. Not stubbing the method of the object of another method.

Any help would be greatly appreciated.

Edit : The VM I aim to test :

class MainViewModel(application: Application): AndroidViewModel(application), WaitingViewModel{

    private val _name = MutableLiveData<String>().apply {
        value = application.getString(R.string.collage_climat)
    }

    val name : LiveData<String> = _name

    override fun notifyNewCollage(collage_name: String) {
        _name.value = collage_name
    }

}

Here is the gradle if you want to check the Mockito version :

dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.2.1'
implementation 'androidx.constraintlayout:constraintlayout:2.0.3'
def navigation_version = '2.3.1'
implementation "androidx.navigation:navigation-fragment-ktx:$navigation_version"
implementation "androidx.navigation:navigation-ui-ktx:$navigation_version"
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation "androidx.navigation:navigation-fragment:$navigation_version"
implementation "androidx.navigation:navigation-ui:$navigation_version"
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.annotation:annotation:1.1.0'
implementation 'androidx.recyclerview:recyclerview:1.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
implementation 'il.co.theblitz:observablecollections:1.4.2'
def espressocore_version = '3.3.0'
androidTestImplementation "androidx.test.espresso:espresso-core:$espressocore_version"
androidTestImplementation "androidx.test.espresso:espresso-core:$espressocore_version"
androidTestImplementation "android.arch.core:core-testing:$lifecycle_version"
def mockito_version = '3.5.5' // For local unit tests on your development machine (also tested on 3.3.3)
testImplementation "org.mockito:mockito-core:$mockito_version" // For instrumentation tests on Android devices and emulators
androidTestImplementation "org.mockito:mockito-android:$mockito_version"
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test:rules:1.0.2'

}
AdrienM
  • 35
  • 5
  • Can you share the view model relevant code? – cutiko Nov 02 '20 at 12:30
  • Yes, but that is irrelevant. I am not mocking or calling my VM class yet. – AdrienM Nov 03 '20 at 08:05
  • Added in the edit. – AdrienM Nov 03 '20 at 08:11
  • How are you initializing the view model, the `MainViewModel`? – cutiko Nov 03 '20 at 13:47
  • I am not, yet. But that is not important because it is the Application mock that is failing. – AdrienM Nov 03 '20 at 19:57
  • Sorry, re watching my post I wasn't very clear – AdrienM Nov 03 '20 at 19:58
  • `when`(applicationMock.getString(R.string.collage_climat)).thenReturn("Climat") is the part that fails. – AdrienM Nov 03 '20 at 19:59
  • If we don't know how you are initializing your view model, we don't know if that is the `application` the view model is receiving as an argument on the constructor – cutiko Nov 03 '20 at 20:12
  • The view model is not initialized in my tests. I cannot stub the fonction getString from my Application mock that is my issue. – AdrienM Nov 04 '20 at 07:39
  • If the view model is not initialized on your test, then it won't use the mock application, so the mocking you are doing it will never happen because the constructor is receiving another application as argument – cutiko Nov 04 '20 at 12:01
  • The Application mock needs the Viewmodel to be initialized ? That does not make sense, outside of the test. It is the Application that is used to initialize my VM and that works. – AdrienM Nov 10 '20 at 09:59
  • No, the view model need to received the mocked application as a constructor argument for then to use it. If you ate doing `mockApplication.getString...` then that application is the application that the view model should use – cutiko Nov 10 '20 at 12:21
  • The Viewmodel has nothing to do with this. In the test, I don't call it, initialize it or do anything with it yet. – AdrienM Nov 11 '20 at 08:36
  • I made a new question https://stackoverflow.com/questions/64784779/mockito-fails-on-stubbing-it-tries-to-execute-the-function-that-should-be-stub I think the issue is the exact same than here but I tried re-explaining what doesn't work and how I understand it should work. – AdrienM Nov 11 '20 at 10:39

1 Answers1

0

Mockito advices against Mocking classes you don't own. So an Application mock is a bad idea. Junit can give you the application context needed : https://developer.android.com/training/testing/junit-runner

For other info about stubbing fail, Mockito fails on stubbing : it tries to execute the function that should be stubbed

AdrienM
  • 35
  • 5