Search code examples
androidunit-testingjunit

How to unit test onInitializeAccessibilityEvent in android


In my android application, I have 3 buttons where when the accessibility focus is cleared, I need to call a method.

To achieve that, I'm doing the following

fun setUpButton() {
...
   registerFocusChangeEvents(button1)
   registerFocusChangeEvents(button2)
   registerFocusChangeEvents(button3)
...
}

...
private fun registerFocusChangeEvents(button: Button){
    button.accessibilityDelegate = object : AccessibilityDelegate() {
    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    override fun onInitializeAccessibilityEvent(host: View?, event: AccessibilityEvent?){
        super.onInitializeAccessibilityEvent(host, event)
        if (event?.eventType == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED){
            testMethod()
        }
    }
}

fun testMethod() {
...
}

In my JUnit test class, I have the following

@Test
fun `test focus shift`() {
    val testClass = spy(TestClass(...))

    val testButton1 = testClass.menu.contentView.findViewById<Button>(R.id.btn1)
    val testButton2 = testClass.menu.contentView.findViewById<Button>(R.id.btn2)
    val testButton3 = testClass.menu.contentView.findViewById<Button>(R.id.btn3)


    // I tried the following
    // testButton1.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED)
    // testButton1.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED)

    // testButton2.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED)
    // testButton2.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED)

    // testButton3.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED)
    // testButton3.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED)

    // testButton1.requestFocus()
    // testButton1.clearFocus()
    // testButton2.requestFocus()
    // testButton2.clearFocus()
    // testButton3.requestFocus()
    // testButton3.clearFocus()


    // testButton1.dispatchTouchEvent(MotionEvent.obtain(0,0, MotionEvent.ACTION_DOWN, 0f, 0f, 0))

    // testButton2.dispatchTouchEvent(MotionEvent.obtain(0,0, MotionEvent.ACTION_DOWN, 0f, 0f, 0))

    // testButton3.dispatchTouchEvent(MotionEvent.obtain(0,0, MotionEvent.ACTION_DOWN, 0f, 0f, 0))

    verify (exactly = 3){ //assertion failed. Method was not called
        testMethod()
    }
}

I've tried the above methods to simulate focus shift from the buttons. however, the test is failing as the testMethod() is never called. So that means, it's unable to trigger the accessibility focus change. I'm not sure why that's the case.

Some other thoughts?


Solution

  • Turns out, all I had to do was

    
    val accessibilityEvent = AccessibilityEvent.obtain(
                AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED
            )
    
    
    button1.accessibilityDelegate.onInitializeAccessibilityEvent(
                button1, accessibilityEvent
            )
    button2.accessibilityDelegate.onInitializeAccessibilityEvent(
                button2, accessibilityEvent
            )
    button3.accessibilityDelegate.onInitializeAccessibilityEvent(
                button3, accessibilityEvent
            )
    verify(exactly = 3) {
                testClass.testMethod()
            }