I am trying to write unit tests for a RecyclerView.ViewHolder class which uses ViewBinding but I am facing issues to inflate my ViewBinding in my test class, having this error when running my test :
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}
I could not find code examples of ViewBinding inflate in test classes, is that possible ? I found this StackOverflow thread but it uses PowerMock to mock a ViewBinding class. I'm using mockK in my project and I think using a real ViewBinding instance would be better in my case.
My ViewHolder looks like this :
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
}
}
}
My test class looks like this. I am using MockK and Robolectric to get application context
@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)
}
}
EDIT: This is the mockK version of the answer from @tyler-v
@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...
}