Мои классы написаны на Котлине, а вот мой 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()
}
Вот метод, вызываемый в презентаторе:
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 !!)
Вот что выброшено:
Caused by: java.lang.IllegalStateException: Application.mInstanc…m", Context.MODE_PRIVATE) must not be null at com.zuum.zuumapp.preferences.SharedPreferenceHandler$Companion.getPrefs(SharedPreferenceHandler.kt:18) at com.zuum.zuumapp.preferences.SharedPreferenceHandler$Companion.access$getPrefs(SharedPreferenceHandler.kt:14) at com.zuum.zuumapp.preferences.SharedPreferenceHandler.(SharedPreferenceHandler.kt:15)
Я хочу получить accessToken, вызвав SharedPreferenceHandler.mInstance.accessToken !! в моем тестовом классе.
Можно ли получить это в моем тестовом методе?
Нет, я использую PowerMock для некоторых моков





Вы не можете использовать Android SharedPreferences в модульном тесте, но вы можете смоделировать вызов своего метода следующим образом:
Mockito.`when`(SharedPreferenceHandler.mInstance.accessToken).thenReturn("token ")
И верните то, что вам нужно.
Вы не должны тестировать свой код таким образом. Вы должны создать интерфейс для класса, над которым хотите имитировать:
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 */
}
}
Можете привести пример с интерфейсом?
Пример с небольшими пояснениями.
«MySharedPreferences» - это просто интерфейс?
Да. Ваш внедренный объект должен быть экземпляром интерфейса. Ваш класс handler должен реализовывать этот интерфейс - когда вы создаете MyPresenter, вы передаете экземпляр класса, реализующего этот интерфейс.
Вы проводите тесты с роботом?