How To Simulate Key Events In Swing JUnit Tests
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) {
Field f = KeyEvent.class.getField("focusManagerIsDispatching");
f.setAccessible(true);
f.set(e, Boolean.TRUE);
c.dispatchEvent(e);
}
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.

February 17th, 2005 at 8:32 pm
Hardcore unit testing in Swing
I’m doing some Swing stuff in my Copious Free Time, basically for fun but also to scratch an old itch. I’m committing myself to high percentages of test coverage (ideally 100%, but I’d sign up for everything above 80%), and this is a good exercise for …
March 7th, 2006 at 10:42 pm
If you need to write many tests for Swing components, it might be an idea to look at existing frameworks. There are some that build on JUnit, for example
http://jfcunit.sourceforge.net/
http://abbot.sourceforge.net/doc/overview.shtml
March 8th, 2006 at 6:06 am
Last time I looked at JFCUnit it required the component to be on screen and have focus, this approach does not which is a lot nicer since it makes the test run faster and allows the test to run in the background so it can be run on a developer’s machine.
August 14th, 2006 at 7:19 pm
I’m using such code to type a key to the control:
1. KeyEvent keyEvent = new KeyEvent(myComponent, KeyEvent.KEY_PRESSED, System.currentTimeMillis(), 0, 83, ’s’, 1);
2. java.lang.reflect.Field f = KeyEvent.class.getField(”focusManagerIsDispatching”); // Unhandled exception type NoSuchFieldException
3. f.setAccessible(true);
4. f.set(keyEvent, Boolean.TRUE); // Unhandled exception type IllegalAccessException
5. ((java.awt.Component)myComponent).dispatchEvent(keyEvent);
But unfortunately I have 2 compilation problems:
1. Unhandled exception type NoSuchFieldException at line 2
2. Unhandled exception type IllegalAccessException at line 4
I found focusManagerIsDispatching field is declared as transient in AWTEvent class and its default value is false. Could you please help me to set its value to true?
August 14th, 2006 at 9:50 pm
Instead of KeyEvent.class.getField, use AWTEvent.class.getField - the original code I posted is incorrect, I thought someone had corrected it but obviously it wasn’t posted as a comment here.
September 26th, 2007 at 7:09 pm
the correct call is AWTEvent.class.getDeclaredField(”focusManagerIsDispatching”)
working example for MouseEvent:
JComponent myComponent = getSomePanel(); //JComponent to be clicked, some panel f.e.
MouseEvent event = new MouseEvent(myComponent, MouseEvent.MOUSE_CLICKED, System.currentTimeMillis(), 0, 0, 0, 1, false);
java.lang.reflect.Field f = AWTEvent.class.getDeclaredField(”focusManagerIsDispatching”);
f.setAccessible(true);
f.set(event, Boolean.TRUE);
((java.awt.Component)myComponent).dispatchEvent(event);