简体   繁体   English

在JUnit测试中处理Swing事件

[英]Handle Swing events in JUnit test

I have Swing java application with network communications to several "Players" that are represented as player objects, each with their own communication thread. 我有Swing Java应用程序,它通过网络与多个“播放器”通信,这些“播放器”表示为播放器对象,每个对象都有自己的通讯线程。 The app has a "Team" object managing all player objects. 该应用程序具有管理所有玩家对象的“ Team”对象。 Several UI components listen to events passed from the players through the Team object. 几个UI组件侦听玩家通过Team对象传递的事件。

In my design, the team object fires all events on the Swing thread using invokeLater, so that the rest of my application does not need to bother with threading issues. 在我的设计中,team对象使用invokeLater触发了Swing线程上的所有事件,因此我的应用程序的其余部分无需担心线程问题。 However, I don't know how I can test the Team class in a JUnit test. 但是,我不知道如何在JUnit测试中测试Team类。

A little more background. 多一点背景。 At first I had the Team object fire its events on the player object threads (no thread switching at all). 最初,我让Team对象在玩家对象线程上触发其事件(根本没有线程切换)。 The Team unit test succeeded, but I got into many threading issues in my UI with invokeLaters and synchronized all over the place. Team单元测试成功,但是我在UI中使用invokeLaters遇到了许多线程问题,并在整个地方进行了同步。 I then decided to simplify the threading model by having the Team object fire events on the Swing thread, but now the Team unit test fails because it does not receive the events. 然后,我决定通过让Team对象在Swing线程上触发事件来简化线程模型,但是现在Team单元测试失败了,因为它没有收到事件。 What to do? 该怎么办?

A solution that comes to mind is to introduce an extra object on top of Team that does the thread switch and keep the original unit test intact, but I do not like the idea of introducing complexity in production code just to make a unit test succeed. 我想到的一个解决方案是在Team之上引入一个额外的对象,该对象进行线程切换并保持原始的单元测试不变,但是我不喜欢在生产代码中引入复杂性只是为了使单元测试成功的想法。

When I've done JUnit testing with EventQueue.invokeLater , I've decoupled myself from that evil static. 当我使用EventQueue.invokeLater完成JUnit测试后,我就使自己脱离了那个邪恶的静态现象。 Create an interface with invokeLater is isDispatchThread methods. 使用isDispatchThread方法创建带有invokeLater的接口。 For production the implementation should just forward to EventQueue . 对于生产,实现应只转发到EventQueue For testing, use your own thread (which can be set up and torn down for each test). 对于测试,请使用您自己的线程(可以为每个测试设置和删除该线程)。

Some other random advice: 其他一些随机建议:

  • Keep the GUI as thin as possible. 保持GUI尽可能薄。
  • Keep threading out of everything else, and everything else out of threading. 保持线程脱离其他所有线程,其他线程脱离线程。
  • Be suspicious of anything claiming to be thread-safe. 怀疑任何声称是线程安全的东西。

Maybe you can use easymock to isolate the classes you want to test, and have the mock objects receive the events and check that they're fired. 也许您可以使用easymock隔离要测试的类,并让模拟对象接收事件并检查它们是否被触发。

I'd recommend EasyMock: http://www.easymock.org/ 我建议使用EasyMock: http//www.easymock.org/

From your story it feels that your unittests are more integration tests, and very intricate. 从您的故事中可以感觉到,单元测试是更多的集成测试,并且非常复杂。 If that's the case, try to simplify and isolate. 如果是这种情况,请尝试简化和隔离。 You've probably read http://junit.sourceforge.net/doc/testinfected/testing.htm 您可能已经阅读了http://junit.sourceforge.net/doc/testinfected/testing.htm

I hope this helps. 我希望这有帮助。

A solution that comes to mind is to introduce an extra object on top of Team that does the thread switch and keep the original unit test intact, but I do not like the idea of introducing complexity in production code just to make a unit test succeed. 我想到的一个解决方案是在Team之上引入一个额外的对象,该对象进行线程切换并保持原始的单元测试不变,但是我不喜欢在生产代码中引入复杂性只是为了使单元测试成功的想法。

I don't know if this is the case here but I often find that the "complexity" that I'm adding is actually a higher level of abstraction that improves the code. 我不知道是否是这种情况,但我经常发现我要添加的“复杂性”实际上是更高级别的抽象,可以改进代码。

The original idea behind mock objects wasn't to make unit testing easier but rather "interface discovery", to create interfaces that represent the abstractions in your ubiquitous language rather than working at the level of the API. 模拟对象背后的最初想法不是使单元测试更容易,而是“接口发现”,创建代表您的通用语言的抽象接口而不是在API级别上工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM