Junit не создает экземпляр общих предпочтений с указанием context.getSharedPreferences(USER_PREFS, Context.MODE_PRIVATE) не должно быть null

#android #kotlin #junit #mockito #sharedpreferences

Вопрос:

Я пишу тестовые примеры JUnit для sharedpreferences, как показано ниже

 class SharedPrefTest {

    private lateinit var context: Context
    private lateinit var userRepo: UserRepo
    private lateinit var sharedPreferences: SharedPreferences

    @Before
    fun setup() {
        context = mock()
        userRepo = UserRepo(context)
    }

    @Test
    fun `check mocked instances are not null`() {
        context assertNotEquals null //mocked successfully
        userRepo assertNotEquals null
    } //PASS

    @Test
    fun `when shared pref instance not null then do further ops`() {
        sharedPreferences = context.getSharedPreferences(USER_PREFS, Context.MODE_PRIVATE)
        sharedPreferences assertNotEquals null
    } //FAIL

    companion object {
        const val USER_PREFS = "userprefs"
    }

}
 

Тем не менее, я получаю сообщение об ошибке ниже.

 context.getSharedPreferences(USER_PREFS, Context.MODE_PRIVATE) must not be null
java.lang.NullPointerException: context.getSharedPreferences(USER_PREFS, Context.MODE_PRIVATE) must not be null
 

Я уже проверил, что context не равен null в отдельном модульном тесте, но все равно его сбой.

Комментарии:

1. Я не понимаю проблемы! Вы уже издевались над контекстом. Почему он должен возвращать не заглушенный (ненулевой) ответ на getSharedPreferences?

2. Используйте Robolectric для написания модульных тестов. Вам не нужно будет вручную имитировать зависимости платформы Android, такие как Context.

3. Проблема @ashu заключается в том, что он не создает экземпляр sharedpreference и выдает нулевую ошибку. Кроме того, ограничено использование Mockito

Ответ №1:

Проблема в том, что он не создает экземпляр sharedpreference и выдает ошибку null.

Почему издевательский объект вызывает его конкретную реализацию? Макет объекта — это заглушка, поведение которой предварительно настроено для конкретных тестовых сценариев. Ожидается, что во время тестов клиенты будут явно указывать, что произойдет, если определенный метод будет вызван для издевательского объекта. Если клиенты не предоставляют такую спецификацию, издевающийся объект часто по умолчанию возвращает нулевые значения для методов, которые не возвращают void; null в случае Mockito (точнее, Java).

Следовательно, вы издеваетесь над context , следовательно, context.getSharedPreferences() возвращает null значение по умолчанию. Поскольку sharedPreferences поле объявлено как тип, не допускающий обнуления Kotlin, присвоение null ему выдает NPE. Вы можете исправить это, вернув издевательский SharedPreferences экземпляр из context.getSharedPreferences() .

 @Test
fun `when shared pref instance not null then do further ops`() {
    val mockPrefs: SharedPreferences = mock()
    `when`(context.getSharedPreferences(USER_PREFS, Context.MODE_PRIVATE))
        .thenReturn(mockPrefs);
    sharedPreferences = context.getSharedPreferences(USER_PREFS, Context.MODE_PRIVATE)
    sharedPreferences assertNotEquals null
}
 

Лучшим подходом было бы использовать платформу модульного тестирования для Android, такую как Robolectric.

 import androidx.test.core.app.ApplicationProvider

@RunWith(RobolectricTestRunner::class)
class SharedPrefTest {

    private lateinit var context: Context
    private lateinit var userRepo: UserRepo
    private lateinit var sharedPreferences: SharedPreferences

    @Before
    fun setup() {
        context = ApplicationProvider.getApplicationContext()
        userRepo = UserRepo(context)
    }

    @Test
    fun `check mocked instances are not null`() {
        context assertNotEquals null
        userRepo assertNotEquals null
    }

    @Test
    fun `when shared pref instance not null then do further ops`() {
        sharedPreferences = context.getSharedPreferences(USER_PREFS, Context.MODE_PRIVATE)
        sharedPreferences assertNotEquals null
    }

    companion object {
        const val USER_PREFS = "userprefs"
    }

}
 

Ссылка: http://robolectric.org/androidx_test /