我正在尝试为使用 ViewBinding 的 RecyclerView.ViewHolder 类编写单元测试,但我在测试类中膨胀 ViewBinding 时遇到问题,在运行测试时出现此错误:
Binary XML file line #38: Binary XML file line #38: Error inflating class <unknown> Caused by: java.lang.UnsupportedOperationException: Failed to resolve attribute at index 5: TypedValue{t=0x2/d=0x7f04015d a=2}
我在测试类中找不到 ViewBinding inflate 的代码示例,这可能吗?我找到了这个 StackOverflow 线程,但它使用 PowerMock 来模拟 ViewBinding 类。我在我的项目中使用 mockK,我认为在我的情况下使用真正的 ViewBinding 实例会更好。
我的 ViewHolder 看起来像这样:
class MemoViewHolder(private val binding: MemoItemBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(data: Memo) {
with(binding) {
// doing binding with rules I would like to test
}
}
}
我的测试课看起来像这样。我正在使用MockK和Robolectric来获取应用程序上下文
@RunWith(RobolectricTestRunner::class)
class MemoViewHolderTest {
private lateinit var context: MyApplication
@Before
fun setUp() {
MockKAnnotations.init(this)
context = ApplicationProvider.getApplicationContext()
}
@Test
fun testSuccess() {
val viewGroup = mockk<ViewGroup>(relaxed = true)
val binding = MemoItemBinding.inflate(LayoutInflater.from(context), viewGroup, false)
}
}
编辑:这是来自@tyler-v 的答案的 mockK 版本
@RelaxedMockK
private lateinit var layoutInflater: LayoutInflater
@RelaxedMockK
private lateinit var rootView: ConstraintLayout // must be the type of the root view in the layout
@RelaxedMockK
private lateinit var groupView: ViewGroup
// mock every views in your layout
@RelaxedMockK
private lateinit var title: TextView
@Before
fun setUp() {
context = ContextThemeWrapper(
ApplicationProvider.getApplicationContext<MyApplication>(),
R.style.AppTheme
)
MockKAnnotations.init(this)
every { layoutInflater.inflate(R.layout.memo_item, groupView, false) } returns rootView
every { rootView.childCount } returns 1
every { rootView.getChildAt(0) } returns rootView
// mock findViewById for each view in the memo_item layout
every { rootView.findViewById<TextView>(R.id.title) } returns title
}
@After
fun tearDown() {
unmockkAll()
}
@Test
fun testBindUser() {
val binding = MemoItemBinding.inflate(layoutInflater, groupView, false)
MemoListAdapter.MemoViewHolder(binding).bind(memoList[0])
// some tests...
}