How To Simulate Key Events In Swing JUnit Tests
By Adrian Sutton
Gianugo Rabellino has been playing with unit testing in Swing – an area that I’ve spent a lot of time complaining about in the past. In his particular case he’s trying to send key events to Swing components programmatically so that his JUnit tests can run automatically. As Gianugo discovered you can’t just create a KeyEvent and send it to Component.dispatchEvent() because it gets rerouted to the focus manager.
Gianugo’s solution was to display the component on screen in a JFrame and make sure it has focus. However, we can go one better – we can simulate the component having focus.
The interactions between Component.dispatchEvent() and the FocusManager are somewhat odd. Component.dispatchEvent() sends the request to the FocusManager without actually checking if it has focus or not. The FocusManager picks the component that has focus and sends the event to it’s Component.dispatchEvent() method. It’s an infinite loop except that the Swing team so helpfully created a package private (read: totally hidden and inaccessible) variable in KeyEvent called focusManagerIsDispatching which tells the Component.dispatchEvent() method not to redirect the event over to the FocusManager but to actually process it like the JavaDoc suggests it will.
So, to make key strokes work with Swing components in JUnit tests we just have to set that variable to true using reflection before we pass the event into Component.dispatchEvent(). The code winds up looking something like (excusing any typos or misremembered method names – I haven’t bothered to compile this):
public void simulateKey(KeyEvent e, Component c) {<br /> Field f = KeyEvent.class.getField("focusManagerIsDispatching");<br /> f.setAccessible(true);<br /> f.set(e, Boolean.TRUE);<br /> c.dispatchEvent(e);<br /> }
If that’s not quite right, check the code for KeyEvent and Component.dispatchEvent to make sure the variable names are right and check the JavaDoc for java.lang.reflect.Field in case I’ve misremembered a method in there somewhere. The concept is definitely sound though.