0

我有一堂课。
我在该类的构造函数中初始化了一个变量。
我调用一个包含while循环的方法,并在每次通过时递增变量。
我写了一个测试来检查该方法被调用后的变量值(并通过一次while循环)。

public class ThreadGenerator implements Runnable {
  private int requests;
  private int limit;

  public ThreadGenerator() {
    requests = 0;
  }

  public void setRequestLimit(int anyLimit) {
    this.limit = anyLimit;
  }

  public void generateThread() {
    new Thread(this).start();
  }

  public void run() {
      while(requests < limit) {
          try {
              // do some stuff
              requests++;
              // close some stuff
          } catch (IOException e) {
            e.printStackTrace();
          }
      }
  }

  public int getRequests() {
      return requests; // calling this method from my tests always returns 0
  }

在我的测试中,当我创建此类的新实例,然后在该类上调用此方法时,它会正确运行并正确递增请求计数器。我已经尝试了几个打印语句来确保这一点。但是,如果我在测试中调用getRequests我的 ThreadGenerator对象,它将返回 0,即初始化的数量。

我的测试代码:

ThreadGenerator threadGenerator = new ThreadGenerator();
threadGenerator.setRequestLimit(1);
threadGenerator.generateThread();
assertEquals(threadGenerator.getRequests(), 1);

如何修改我在构造函数中初始化的这个变量并在我的测试套件中访问它?

4

2 回答 2

5

请记住,仅仅因为您要求 Java 使用 Runnable 创建一个新线程,并不意味着该run()方法将立即被调用。这很可能是在第一次assertEquals发生之前发生的。run

您可能希望返回线程并join在生成的线程上调用测试,这将确保线程运行直到它死亡,可能有一个短暂的超时。

/* in the system under test */
@VisibleForTesting Thread generateAndReturnThread() {
  Thread thread = new Thread(this);
  thread.start();
  return thread;
}

public void generateThread() {
  generateAndReturnThread();
}

/* in the test */
@Test public void yourTest() {
  ThreadGenerator threadGenerator = new ThreadGenerator();
  threadGenerator.setRequestLimit(1);

  // wait up to a second for thread to complete
  threadGenerator.generateThreadAndReturn().join(1000);

  assertEquals(threadGenerator.getRequests(), 1);
}

旁注:考虑AtomicInteger您的请求类,如果多个线程可能会修改requests. 这将有助于防止两个不同的线程相互修改requests和覆盖。

于 2013-01-10T06:17:33.527 回答
1

除了上面的答案,考虑将变量声明为 volatile,这样你就可以在另一个线程增加变量后实际获得最新的值。

于 2013-01-10T06:47:03.433 回答