Single Swing Testing

I am writing a TotalCommander application. I have a separate component for a list of files and a model for it. The model supports listeners and issues a notification of events such as CurrentDirChanged , etc. In the following way:

 private void fireCurrentDirectoryChanged (final IFile dir) {
     if (SwingUtilities.isEventDispatchThread ())
         for (FileTableEventsListener listener: tableListeners)
             listener.currentDirectoryChanged (dir);
     else {
         SwingUtilities.invokeLater (new Runnable () {
             public void run () {
                 for (FileTableEventsListener listener: tableListeners)
                     listener.currentDirectoryChanged (dir);
             }
         });
     }
 }

I wrote a simple test for this:

 @Test
 public void testEvents () throws IOException {
     IFile testDir = mockDirectoryStructure ();
     final FileSystemEventsListener listener = 
                 context.mock (FileSystemEventsListener.class);
     context.checking (new Expectations () {{
         oneOf (listener) .currentDirectoryChanged (with (any (IFile.class)));
     }});

     FileTableModel model = new FileTableModel (testDir);
     model.switchToInnerDirectory (1);
 }

This does not work because there is no EventDispatchThread . Is there a unit test way to do this inside a headless assembly?

unit-testing java swing jmock

+7
java unit-testing swing jmock
source share
5 answers

Please note that, firstly, unit testing on UI stuff is always difficult because you have to mock a lot of things that are simply not available. Therefore, the main goal when developing applications (of any type) is to always try to separate the user interface material from the main application logic as much as possible. With strong dependencies here, make unit testing really hard, mostly a nightmare. This is usually used when using templates such as MVC , where you mostly check your controller classes, and view classes do nothing but build a user interface and delegate your actions and events to controllers. This separates responsibilities and makes testing easier.

In addition, you do not have to check things that are already provided by the framework, for example, check whether events are triggered correctly. You should just check the logic you write yourself.

+10
source share

Check out this :

FEST is a collection of libraries released under the Apache 2.0 license, whose task is to simplify software testing. It consists of various modules that can be used with TestNG or JUnit ...

+12
source share

Check out the uispec4j project. This is what I use to test my user interfaces.

www.uispec4j.org

+2
source share

I think the testing issue reveals a code issue. It does not have to be a model task to decide if it works in the sending stream, which is too many responsibilities. It should simply complete its notification task and let the calling component decide whether to call it directly or invokeLater. This component should be part of the code that knows about Swing threads. This component should know only files, etc.

+2
source share

I only work with jMock for two days ... so please excuse me if there is a more elegant solution. :)

Your FileTableModel seems to depend on SwingUtilities ... do you consider the mockery of the SwingUtilities you use? One way that smells like a hack but solves the problem is to create an interface, say, ISwingUtilities, and implement the dummy class MySwingUtilities, which simply goes into the real SwingUtilities. And then in the test case, you can mock the interface and return true for isEventDispatchThread.

 @Test public void testEventsNow() throws IOException { IFile testDir = mockDirectoryStructure(); final ISwingUtilities swingUtils = context.mock( ISwingUtilities.class ); final FileSystemEventsListener listener = context.mock(FileSystemEventsListener.class); context.checking(new Expectations() {{ oneOf( swingUtils ).isEventDispatchThread(); will( returnValue( true ) ); oneOf(listener).currentDirectoryChanged(with(any(IFile.class))); }}); FileTableModel model = new FileTableModel(testDir); model.setSwingUtilities( swingUtils ); // or use constructor injection if you prefer model.switchToInnerDirectory(1); } 
+1
source share

All Articles