我写一个TotalCommander中一样的应用。 我有一个文件列表单独的组件,并为它的典范。 型号支持的听众和问题,像事件通知CurrentDirChanged
在以下方式等:
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);
}
});
}
}
我写了一个简单的测试此:
@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);
}
这是不行的,因为没有EventDispatchThread
。 有没有什么办法进行单元测试这个无头内搭?
单元测试的Java Swing JMock的
注意,一般来说对UI的东西单元测试是很困难的,因为你必须模拟出了很多的东西,这仅仅是不可用的。
因此显影(任何类型)的应用程序时的主要目标是保持在从主应用程序逻辑尽可能尝试单独UI东西。 这里有较强的依赖性,使得单元测试真的很辛苦,基本上是一个噩梦。 这通常是通过使用类似的模式利用MVC样的方式,在这里主要是测试你的控制器类和视图类做的无非就是构建UI和委派他们的行动和事件的控制器。 这种分离的职责,使测试更容易。
而且你不一定检验这些框架提供已经试验等事件是否正确解雇的事情。 您应该只是测试你自己写的逻辑。
看看这个 :
FEST是库的集合,根据发布的Apache 2.0许可证 ,其使命是简化软件测试。 它是由各种模块,其可与可使用的TestNG的或JUnit的 ...
检查uispec4j项目。 这就是我用它来测试我的用户界面。
www.uispec4j.org
我想与测试问题揭示与代码中的问题。 它不应该真正成为模特的工作,以决定是否在调度线程中运行,这是太多的责任。 它应该只是做它的通知工作,并让调用组件决定是否直接或invokeLater的调用它。 这部分应该是在知道的Swing线程代码的一部分。 该组件才知道有关文件和等。
我只一直在与JMock的两天...所以请原谅我,如果有一个更优雅的解决方案。 :)
好像你FileTableModel取决于SwingUtilities类的......你有没有考虑嘲笑你使用SwingUtilities类的? 闻起来像一个黑客,但可以解决这个问题是创建一个接口的一种方法,说ISwingUtilities,并简单地转发实现的虚拟类MySwingUtilities,要真正SwingUtilities的。 然后在您的测试情况下,你可以嘲笑了接口和isEventDispatchThread返回true。
@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);
}