Почему "getSharedPreferences" возвращает null в модульном тестировании? - PullRequest
0 голосов
/ 29 мая 2018

Мои занятия написаны на Kotlin, а вот мой SharedPreferenceHandler

   class SharedPreferenceHandler(sharedPrefs: SharedPreferences) {

        companion object {
            var mInstance: SharedPreferenceHandler = SharedPreferenceHandler(getPrefs())

            private fun getPrefs(): SharedPreferences {
                return Application.mInstance.getSharedPreferences(
                        "myApp", Context.MODE_PRIVATE)
            }

            fun getInstance(): SharedPreferenceHandler {
                return mInstance
            }
        }

        private var sharedPreferences = sharedPrefs

        var accessToken: String?
            get() = sharedPreferences.getString(SharedPreference.ACCESS_TOKEN.name, null)
            set(token) = sharedPreferences.edit().putString(SharedPreference.ACCESS_TOKEN.name, token).apply()
}

Вот метод, который вызывается в Presenter:

 override fun reload(vm: ViewModel) {
        super.updateViewModel(vm) {
           //some stuffs
        }
    }

Вот мой метод тестирования:

@Test
public void reload() {
    when(SharedPreferenceHandler.Companion.getMInstance().getAccessToken()).thenReturn("234234234234234");

    presenter.reload(viewModel);
}

В обработчике из super.updateViewModel (vm) Я называю «SharedPreferenceHandler.mInstance.accessToken !!)»

Вот что выброшено:

Причина: java.lang.IllegalStateException: Application.mInstanc… m ", Context.MODE_PRIVATE) не должен иметь значение null в com.zuum.zuumapp.preferences.SharedPreferenceHandler $ Companion.getPrefs (SharedPreferenceHandler.kt: 18) в com.zuum.zuumapp.preferences.SharedPreferenceHandler $ Companion.access $ getPrefs (SharedPreferenceHandler.kt: 14) в com.zuum.zuumapp.preferences.SharedPreferenceHandler. (SharedPreferenceHandler.kt: 15)

1019 до 1019получить accessToken, вызвав «SharedPreferenceHandler.mInstance.accessToken !!» в моем тестовом классе.

Возможно ли получить это в моем тестовом методе?

Ответы [ 2 ]

0 голосов
/ 30 мая 2018

Вы не должны проверять свой код таким образом.Вы должны создать интерфейс для класса, который хотите смоделировать:

interface MySharedPreferences {
    fun getAccessToken(): String
}

Пусть ваш SharedPreferencesHandler реализует этот интерфейс.Затем в своем презентаторе (или другом классе, который вы хотите протестировать) вставьте зависимости (например, с помощью конструктора или фреймворка, например, Dagger / Kodein) в ваш объект.Тогда есть возможность легко издеваться над этим интерфейсом.Я предполагаю, что в @Before вы создаете класс, который вы тестируете, а затем просто передаёте в качестве параметра свой поддельный SharedPreferencesHandler.

Тестирование со статическими зависимостями возможно, но сложно, но многие люди считают статические зависимости антивирусными.-шаблон).Как это сделать, описано здесь: Как выполнить юнит-тестирование Android и макетировать статический метод

Пример:

 class MyPresenter(val sp: MySharedPreferences) {
     /* some code here */
     fun validateToken() {
         if (sp.getAccessToken() == "") throw new Exception()
     }
 }  

Как вы видите, sp вводится вэтот класс в качестве параметра.Обычно вы не создаете представления / докладчиков и т. Д. Непосредственно в коде, а с помощью DI-фреймворка (например, Dagger или Kodein).В любом случае, статические зависимости непросто проверить.Внедренные зависимости интерфейса могут быть смоделированы, и вы работаете не с объектом, а с поведением (так что это больший уровень абстракции).Итак, теперь в вашем тесте все, что вам нужно сделать, это:

class MyTest() {

    @Mock lateinit var sharedPreferencesMock: MySharedPreferences
    lateinit var instance: MyPresenter

    @Before
    fun setUp() {
        instance = MyPresenter(sharedPreferencesMock)
    }

    @Test
    fun testSomething() {
        `when`(sharedPreferencesMock.getAccessToken()).thenReturn("myAccessToken")
        /* here is your test body */
    }
} 
0 голосов
/ 29 мая 2018

Вы не можете использовать Android SharedPreferences в модульном тесте, но можете смоделировать вызов метода следующим образом:

Mockito.`when`(SharedPreferenceHandler.mInstance.accessToken).thenReturn("token ")

и вернуть то, что вам нужно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...