如何编写JUnit测试用例来测试线程和事件

我有一个在一个(主)线程中工作的java代码。 从主线程,我产生一个新线程,我在其中进行服务器调用。 服务器调用完成后,我在新线程中做了一些工作,然后代码加入主线程。

我正在使用eclipse Jobs来进行服务器调用。

我想知道,我如何为此编写一个JUnit测试用例。

您可能需要重新构建代码,以便可以轻松地对其进行测试。

我可以看到几个不同的测试区域:

  1. 线程管理代码:启动线程并可能等待结果的代码
  2. “worker”代码在线程中运行
  3. 多个线程处于活动状态时可能导致的并发问题

构建您的实现,以便您的线程管理代码与Worker的详细信息无关。 然后,您可以使用Mock Workers来启用线程管理测试 – 例如,以某种方式失败的Mock Worker允许您测试管理代码中的某些路径。

实现Worker代码,以便它可以单独运行。 然后,您可以使用服务器的模拟单独对此进行unit testing。

对于并发测试,Abhijeet Kashnia提供的链接将有所帮助。

这就是ConcurrentUnit的创建方式。 一般用法是:

  1. 产生一些线程
  2. 让主线程等待或睡眠
  3. 从工作线程中执行断言(通过ConcurrentUnit报告回主线程)
  4. 所有断言完成后,从其中一个工作线程恢复主线程

有关详细信息,请参阅ConcurrentUnit页面。

我建议你使用一个模拟框架,以确认服务器调用确实已经完成。 至于线程unit testing: unit testingmultithreading应用程序

Abhijeet Kashnia提供的资源可能会有所帮助,但我不确定您要实现的目标。

您可以使用模拟进行unit testing来validation您的代码,这不会测试并发性,但会提供覆盖率。 您可以编写集成测试来validation是否以您期望的方式创建和连接线程。但是,这不能保证不会出现并发问题。 大多数并发问题是由时间错误引起的,这些错误是无法预测的,因此无法准确测试。

这是我使用thread.start测试asynchrone方法的解决方案:

public class MyClass { public void doSomthingAsynchrone() { new Thread(() -> { doSomthing(); }).start(); } private void doSomthing() { } } @RunWith(PowerMockRunner.class) @PrepareForTest(MyClass.class) public class MyClassTest { ArgumentCaptor runnables = ArgumentCaptor.forClass(Runnable.class); @InjectMocks private MyClass myClass; @Test public void shouldDoSomthingAsynchrone() throws Exception { // create a mock for Thread.class Thread mock = Mockito.mock(Thread.class); // mock the 'new Thread', return the mock and capture the given runnable whenNew(Thread.class).withParameterTypes(Runnable.class) .withArguments(runnables.capture()).thenReturn(mock); myClass.doSomthingAsynchrone(); runnables.getValue().run(); /** * instead of 'runnables.getValue().run();' you can use a real thread.start * * MockRepository.remove(Thread.class); * Thread thread = new Thread(runnables.getValue()); * thread.start(); * thread.join(); **/ verify(myClass, times(1)).doSomthing(); } } 

我猜你可能已经完成了你的模拟代码,可能需要一个简单的集成测试来确保你的服务器调用工作。

测试线程的困难之一来自于它们的本质 – 它们是并发的。 这意味着您需要编写JUnit测试代码,在测试代码结果之前,该代码必须等到线程完成其工作。 这不是测试代码的一种非常好的方法,并且可能不可靠,但通常意味着您对代码是否正常工作有所了解。

例如,您的代码可能类似于:

 @Test public void myIntegrationTest() throws Exception { // Setup your test // call your threading code Results result = myServerClient.doThreadedCode(); // Wait for your code to complete sleep(5); // Test the results assertEquals("some value",result.getSomeValue()); } private void sleep(int seconds) { try { TimeUnit.SECONDS.sleep(seconds); } catch (InterruptedException e) { e.printStackTrace(); } } 

我真的不喜欢这样做,喜欢嘲笑并同意其他答案。 但是,如果你需要测试你的线程,那么这是我发现的一种方法。