测试并发代码的行为

时间:2015-07-21 15:08:12

标签: java multithreading testing

我有一个对象,它在收到一些消息后异步改变状态(内部线程改变状态)。状态改变后我想测试一些行为。

所以基本上我需要做一些事情:

  1. 创建对象
  2. 向对象发送消息
  3. 等待状态改变
  4. 测试行为
  5. 但是,状态是私有并且未公开。

    是否有一个优雅的解决方案,不需要暴露状态?

    如果不是 - 要求更改主代码以使其更易于测试是否合理?

3 个答案:

答案 0 :(得分:1)

测试异步代码的一般模式是阻塞主测试线程,而不是在取消阻塞主测试线程之前执行异步回调中的某些内容。以下是使用ConcurrentUnit的示例:

final Waiter waiter = new Waiter();

bus.registerMessageHandler(message -> {
  waiter.assertEquals(message.body(), "foo");
  waiter.resume();
});

waiter.await(5000);

此测试会创建一个等待5秒钟的服务员。针对消息总线注册的回调将在恢复服务员之前在单独的线程中执行断言,以便测试可以完成。

问题是你显然需要能够将某种回调/处理程序插入到应用程序中。如果你只是在等待一些状态改变而你完全无法看到它,那么就没有太多可以断言状态发生了变化。

答案 1 :(得分:-1)

如果状态是私有的,则只能在其自己的类(https://docs.oracle.com/javase/tutorial/java/javaOO/variables.html)中访问它,这意味着如果不修改类,您将无法从新创建的对象中获取状态。
现在,为了进行一些测试而修改类是否合理是多种因素:

  • 有多少人在处理该代码?
  • 已有多少人使用过该版本的代码?
  • 如果将状态变量更改为public并添加getter方法,则会遇到完整性问题。

因此,如果不详细了解您的软件组织,我无法告诉您这是否合理。
我希望这个简短的回答可以帮助你解决问题。

答案 2 :(得分:-1)

您可以使用Reflection访问相关的私有字段,假设您有权这样做。

  Foo bar = new Foo();
  bar.setValue(true);

  Field field = Foo.class.getDeclaredField("value");
  field.setAccessible(true);
  Object value = field.get(bar);

这将获得存储在类中的私有变量中的值。

这非常难看,你可能不应该这样做,但是如果你真的需要避免改变你正在测试的课程那么它应该可以做到。