FragmentScenario
добавляет ваш Фрагмент в пустой класс активности - androidx.fragment.app.testing.FragmentScenario$EmptyFragmentActivity
, упомянутый в трассировке стека.
Это означает, что ваш Фрагмент не в экземпляре вашего InspectionActivity
класс. Вы получаете сбой, потому что ваш метод clearRFIDCache()
преобразует действие в InspectionActivity
.
Если вы хотите проверить свой фрагмент в конкретном экземпляре действия и иметь сильную связь между двумя, вам нужно использовать ActivityScenario
и вручную добавить свой фрагмент к этому действию, а не FragmentScenario
, который не дает вам никакого контроля над используемым вами классом деятельности.
В идеале вы не должны'1017 * тесно связывает ваш фрагмент с вашей деятельностью. Например, вы можете предоставить FragmentFactory
, который использует инжекцию конструктора для добавления интерфейса, который требуется вашему Фрагменту, вместо того, чтобы ваш Фрагмент достигал Действия для прямого вызова методов, как обсуждалось в Фрагментах : прошлое, настоящее и будущееtalk :
// Create an interface for what methods you want to expose
interface Inspector {
// whatever methods you want
}
// Change your Fragment to take in that interface
class ContentFragment(val inspector: Inspector) : Fragment() {
fun clearRFIDCache() {
// Now you can call methods on inspector here
// without casting your Activity
}
}
private class InspectionActivityFactory(
inspector: Inspector
) : FragmentFactory() {
override fun instantiate(
classLoader: ClassLoader,
className: String
) = when (className) {
ContentFragment::class.java.name -> ContentFragment(inspector)
else -> super.instantiate(classLoader, className)
}
}
// Now update your InspectionActivity to implement the interface
// and pass itself into an instance of the FragmentFactory you created
class InspectionActivity : AppCompatActivity(), Inspector {
override fun onCreate(savedInstanceState: Bundle?) {
supportFragmentManager.fragmentFactory =
InspectionActivityFactory(this)
super.onCreate(savedInstanceState)
...
}
}
launchFragment
принимает параметр factory
, который позволяет вводить тестовый интерфейс, гарантируя, что вы можете проверить получение ожидаемых обратных вызовов, не полагаясь на определенный подклассвашей деятельности. При использовании Kotlin вы также можете использовать конечный лямбда-синтаксис для создания фрагмента и вообще пропустить создание фабрики:
@RunWith(AndroidJUnit4::class)
class ExampleUnitTest {
@Test
fun `inspection failure point to location mapping is correct`() {
val inspector = mock(Inspector::class.java)
val scenario = launchFragment {
ContentFragment(inspector)
}
scenario.onFragment { fragment ->
//TODO: test logic
}
}
...
}