Доступ к главной теме от сопрограмм - PullRequest
0 голосов
/ 04 апреля 2019

Я тестирую класс, который показывает alertDialog, и я хочу провести некоторое тестирование пользовательского интерфейса. Проблема заключается в том, что и диалог, и задача эспрессо должны выполняться в потоке пользовательского интерфейса, но задача эспрессо не выполняется, она ожидает, когда «кто-то» выберет элемент из пользовательского интерфейса.

Таким образом, тест намеревается показать alertDialog и выбрать элемент (с эспрессо), а затем подтвердить, что возврат из функции, которая показала пользовательский интерфейс, возвращает значение выбранного элемента.

Это класс, который я хочу проверить:

class UserSelector(private val activity: Activity) {

    suspend fun showUserSelectionDialog(usersAndEmails: Map<String, String>) = suspendCoroutine<String?> { cont ->
        val users: Array<String> = usersAndEmails.keys.toTypedArray()
        val builder = AlertDialog.Builder(activity)
        builder.setTitle(com.build38.fido.asm.R.string.select_username)
                .setItems(users) { _, which ->
                    val username = users[which]
                    cont.resume(usersAndEmails[username])
                }
                .setCancelable(true)
                .setOnCancelListener {
                    cont.resume(null)
                }
        val dialog: AlertDialog = builder.create()
        dialog.show()
    }
}

Это тестовый класс:

@Rule @JvmField
var mActivityRule: ActivityTestRule<MainActivity> = ActivityTestRule(MainActivity::class.java)

private lateinit var userSelector: UserSelector

@Before
fun setUp() {
    userSelector = UserSelector(mActivityRule.activity)
}

@Test
fun clickOnFirstItem() {
    val usernamesAndEmails = mutableMapOf<String,String>()
    usernamesAndEmails.put("Username1", "Email1")
    usernamesAndEmails.put("Username2", "Email2")
    var email = ""
    runBlocking {
        withContext(Dispatchers.Main) {
            email = userSelector.showUserSelectionDialog(usernamesAndEmails)!!
        }
        onView(withText("Username2"))
                .perform(ViewActions.click())

    }
    assertEquals("Username1", email)
}

1 Ответ

0 голосов
/ 04 апреля 2019

Щелчок не выполняется, поскольку он ожидает, чтобы диалоговое окно функционировало синхронно.withContext выполняет код синхронно в другом контексте (который в большинстве случаев является просто другим потоком).

Здесь вы на самом деле хотите асинхронное выполнение диалогового окна.Поэтому используйте launch для вызова сопрограммы, которая будет выполняться асинхронно.Вам не нужно ждать его в конце runBlocking благодаря структурированному параллелизму.

@Test
fun clickOnFirstItem() {
    val usernamesAndEmails = mutableMapOf<String,String>()
    usernamesAndEmails.put("Username1", "Email1")
    usernamesAndEmails.put("Username2", "Email2")
    var email = ""
    runBlocking {
        launch(Dispatchers.Main) {
            email = userSelector.showUserSelectionDialog(usernamesAndEmails)!!
        }
        onView(withText("Username2"))
                .perform(ViewActions.click())

    }
    assertEquals("Username1", email)
}
...