Тест класса инструментального модуля - не удается создать обработчик внутри потока, который не вызвал Looper.prepare()
Извините, я посмотрел учебники повсюду и не нашел ответ, который я ищу. Сейчас я следую учебному пособию Google здесь: https://developer.android.com/training/testing/unit-testing/instrumented-unit-tests.html
Я пытаюсь создать инструментальный тест, и когда я его запускаю, я получаю сообщение об ошибке: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
Итак, мой тест выглядит следующим образом:
package testapp.silencertestapp;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class MainActivityTest {
private MainActivity testMain;
@Before
public void createActivity(){
testMain = new MainActivity();
}
@Test
public void checkFancyStuff(){
String time = testMain.createFancyTime(735);
assertThat(time, is("07:35"));
}
}
И я пытаюсь запустить метод внутри основной деятельности следующим образом (это выдержка):
public class MainActivity extends AppCompatActivity {
private TimePicker start;
private TimePicker end;
@Override
protected void onCreate(Bundle savedInstanceState) {
start = (TimePicker) findViewById(R.id.startPicker);
end = (TimePicker) findViewById(R.id.endPicker);
}
String createFancyTime(int combinedTime) {
StringBuilder tempString = new StringBuilder(Integer.toString(combinedTime));
if(tempString.length()==4){
tempString = tempString.insert(2, ":");
}
else if (tempString.length()==3){
tempString = tempString.insert(1, ":");
tempString = tempString.insert(0, "0");
}
else if(tempString.length()==2){
tempString = tempString.insert(0, "00:");
}
else if(tempString.length()==1){
tempString = tempString.insert(0, "00:0");
}
return tempString.toString();
}
Я предполагаю, что это проблема, потому что я не запускаю службу правильно или что-то в этом роде - я пытался использовать несколько способов, но я просто везде получаю ошибки. Поиск здесь и эта ошибка популярны, но не в связи с тестированием, поэтому интересно, может ли кто-нибудь любезно указать мне правильное направление, чтобы я мог проверить методы в этом классе?
2 ответа
Ошибка происходит потому, что Looper
неправильно настроена для тестируемой системы (MainActivity
).
В то время как Activity
, Fragment
и т.д. имеют конструкторы без аргументов, они предназначены для создания экземпляров ОС Android и, как таковые, вызывают MainActivity = new Activity()
недостаточно, чтобы получить полностью работающий экземпляр звезды смерти в комплекте с Handler
а также Looper
,
Есть два варианта, если вы хотите продолжить тестирование:
Если вы хотите проверить реальный экземпляр Activity, это должен быть инструментальный тестовый модуль (
androidTest
неtest
) и@TestRule
заставит ОС Android правильно создать экземпляр Activity:@Rule public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule(MainActivity.class);
Если вы предпочитаете продолжать писать локальные модульные тесты, которые запускаются в IDE, вы можете использовать http://robolectric.org/. Robolectric будет корректно корректировать поведение теневой активности, чтобы вы могли тестировать компоненты, которые полагаются на
Looper
и т. д. Обратите внимание, что здесь есть некоторые настройки.
Вот как я это решил. Я запустил тестовый пример в основном потоке, используя
runOnMainSync
. Вот полное решение:
@RunWith(AndroidJUnit4::class)
class AwesomeViewModelTest {
@Test
fun testHandler() {
getInstrumentation().runOnMainSync(Runnable {
val context = InstrumentationRegistry.getInstrumentation().targetContext
// Here you can call methods which have Handler
})
}
}