Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Possible to mock/test Android ViewBinding interactions?

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?

like image 466
Flo We Avatar asked Oct 15 '22 04:10

Flo We


1 Answers

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.

like image 168
Glo Avatar answered Oct 19 '22 02:10

Glo