java 对 Swing 组件进行单元测试
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1480843/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Unit testing a Swing component
提问by Ula Krukar
I am writing a TotalCommander-like application. I have a separate component for file list, and a model for it. Model support listeners and issues a notification for events like CurrentDirChangedetc. in following manner:
我正在编写一个类似 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);
}
});
}
}
I've written 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 any way to unit test this inside the headless build?
这不起作用,因为没有EventDispatchThread. 有没有办法在无头构建中对此进行单元测试?
unit-testing java swing jmock
单元测试 java swing jmock
采纳答案by Juri
Note, generally speaking unit testing on UI stuff is always difficult because you have to mock out a lot of stuff which is just not available.
Therefore the main aim when developing applications (of any type) is always to try to separate UI stuff from the main application logic as much as possible. Having strong dependencies here, make unit testing really hard, a nightmare basically. This is usually leveraged by using patterns like a MVCkind of approach, where you mainly test your controller classes and your view classes do nothing than constructing the UI and delegating their actions and events to the controllers. This separates responsibilities and makes testing easier.
请注意,一般来说,对 UI 内容进行单元测试总是很困难的,因为您必须模拟出很多不可用的内容。
因此,开发应用程序(任何类型)的主要目标始终是尽可能将 UI 内容与主要应用程序逻辑分开。这里有很强的依赖关系,使单元测试变得非常困难,基本上是一场噩梦。这通常是通过使用像MVC类型的方法这样的模式来利用的,在这种模式下,您主要测试控制器类,而您的视图类除了构建 UI 并将它们的操作和事件委托给控制器之外什么都不做。这将职责分开并使测试更容易。
Moreover you shouldn't necessarily test things which are provided by the framework already such as testing whether events are correctly fired. You should just test the logic you're writing by yourself.
此外,您不必测试框架已经提供的内容,例如测试事件是否正确触发。您应该只测试自己编写的逻辑。
回答by Ula Krukar
Look this:
看这个:
FEST is a collection of libraries, released under the Apache 2.0 license, whose mission is to simplify software testing. It is composed of various modules, which can be used with TestNGor JUnit...
FEST 是在Apache 2.0 许可下发布的库集合,其使命是简化软件测试。它由各种模块组成,可以与TestNG或JUnit一起使用......
回答by Juri
Check the uispec4j project. That's what I use to test my UIs.
检查 uispec4j 项目。这就是我用来测试我的 UI 的内容。
回答by Steve Freeman
I think the problem with testing is revealing a problem with the code. It shouldn't really be the model's job to decide whether it's running in the dispatch thread, that's too many responsibilities. It should just do its notification job and let a calling component decide whether to call it directly or to invokeLater. That component should be in the part of the code that knows about Swing threads. This component should only know about files and such.
我认为测试的问题在于揭示了代码的问题。决定它是否在调度线程中运行不应该真的是模型的工作,那是太多的责任。它应该只是做它的通知工作,让调用组件决定是直接调用它还是调用它。该组件应该位于了解 Swing 线程的代码部分。这个组件应该只知道文件等。
回答by Philip Davis
I've only been working with jMock for two days... so please excuse me if there is a more elegant solution. :)
我只和 jMock 一起工作了两天......所以如果有更优雅的解决方案,请原谅我。:)
It seems like your FileTableModel depends on SwingUtilities... have you considered mocking the SwingUtilities that you use? One way that smells like a hack but would solve the problem would be to create an interface, say ISwingUtilities, and implement a dummy class MySwingUtilities that simply forwards to the real SwingUtilities. And then in your test case you can mock up the interface and return true for isEventDispatchThread.
似乎您的 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);
}

