5

currently trying to test the interactions with ViewBinding classes in Unit Tests

"Invalid Input" should {
    "disable the LoginButton" {
        val viewBinding: FrLoginBinding = mockk()

        InvalidInputViewStateBinder.bind(InvalidInput, viewBinding)

        verify { viewBinding.loginButton.isEnabled = false }
    }
}

something like this is what i had in mind. The Views in the ViewBinding are public final Properties and cannot easily be mocked. At least i'm unable to. Passing a View mock to create the ViewBinding also doesn't work, as i'd have to mock findViewById for it.

Has anyone tried this out and got it to work?

Flo We
  • 325
  • 2
  • 12

1 Answers1

4

I came across this same issue. Here is how I resolved it


@RunWith(PowerMockRunner::class)
@PrepareForTest(MyLayoutBinding::class)
class MyTestClass {

    @Mock
    lateinit var mMockViewBinding: MyLayoutBinding

    @Mock
    lateinit var mMockView: View

    @Mock
    lateinit var mMockTitleTv: TextView

    @Mock
    lateinit var mMockRootView: ConstraintLayout

    @Before
    fun setup() {
        MockitoAnnotations.initMocks(this)
        PowerMockito.mockStatic(MyLayoutBinding::class.java)
        whenever(MyLayoutBinding.bind(mMockView)).thenReturn(mMockViewBinding)
        
        // Use Whitebox for each view component in the layout.
        Whitebox.setInternalState(mMockBinding, "title", mMockTitleTv)
        
        // Because 'getRoot' is part of the ViewBinding interface, we just mock the method.
        whenever(mMockBinding.root).thenReturn(mMockRootView)
    }


}

Use Whitebox to set the properties (i.e. the views by id) and mock the getRoot() interface method to set the root to your mocked root view.

Glo
  • 161
  • 1
  • 6
  • so for each view of the LayoutBinding i need to provide a mock and set the internal state with Whitebox? Even if have no assertions on them? – Flo We Mar 05 '21 at 10:24
  • @FloWe You should be able to just mock the specific view and set it with whitebox. – Glo May 12 '21 at 18:58
  • Do you mean `mMockBinding.root` or `mMockViewBinding.root` as per your provided snippet? – Ankush Nov 25 '22 at 01:39