1

I'm trying to write a JUnit test. My problem is that my threads can't see the object I have created in the sequential bit of code (code before starting the threads).

public class MyTest implements Runnable {

    private MyClass mc;

    /**
     * @throws InterruptedException
     */
    @Test
    public void parallelTest() throws InterruptedException {
        this.mc = new MyClass();
        Thread thread1 = new Thread(new MyTest());
        Thread thread2 = new Thread(new MyTest());
        thread1.join();
        thread2.join();
        thread1.start();
        thread2.start();
        // TODO the test
    }

    public void run() {
       if(mc != null) {
          System.out.println("ph not null");
       } else {
          System.out.println("ph null"); // THIS CODE GETS EXECUTED
       }
       // some code
    }
}

See the comment in the run method above. My object is null but I want both threads to be able to access the MyClass object. How come they see null? I tried using a constructor but I think the interface prevented me from passing a parameter to the constructor.

Many thanks.

4

3 回答 3

5

每个可运行实例都是使用new MyTest(). 并且 MyTest 类没有任何构造函数来初始化字段private MyClass mc;。所以它有它的默认值:null。

每个对象都有自己的实例字段。这是OO的基本原则。

于 2013-07-20T16:51:37.850 回答
0

我解决了:)。我会给出一些 +1,因为我遇到了一些进一步的问题:

  1. @Jeffrey:是的,start而且join是错误的方式
  2. @JB Nizet:谢谢..我的问题有一个疯狂的错字(编辑过的问题)

@Itay Maman 和我有同样的想法,但它不起作用——JUnit 不允许我将参数传递给它的构造函数。

解决方案是不使用构造函数,而是使用 @BeforeClass 注解和init方法来实例化MyClass.

public class MyTest implements Runnable {

    private static MyClass mc;

    @BeforeClass
    public static void init() {
        mc = new MyClass();
    }

    @Test
    public void parallelTest() throws InterruptedException {
        Thread thread1 = new Thread(new MyTest());
        Thread thread2 = new Thread(new MyTest());
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        // my assertion about mc object goes here
    }

    public void run() {
        // code to test
    }
}

这个单元测试仍然不能完美地测试代码,因为执行路径是不确定的,所以它有时会通过,有时会失败。也许我也会添加一些更细粒度的测试。

于 2013-07-20T18:59:07.463 回答
0

您初始化.mc字段,this但随后创建两个新实例MyTest(其中.mc未初始化,即:它是null)并将这些实例传递给您的线程。

因此解决方案非常简单:传递this给线程。

[编辑]

此外,我必须切换 .start() 和 .join() 调用的顺序 - 等待线程完成(即join)仅在线程先前已启动时才有意义。

package p1;

import org.junit.Test;

public class MyTest implements Runnable {

  private MyClass mc;

  /**
   * @throws InterruptedException
   */
  @Test
  public void parallelTest() throws InterruptedException {
      this.mc = new MyClass();
      Thread thread1 = new Thread(this);
      Thread thread2 = new Thread(this);
      thread1.start();
      thread2.start();
      thread1.join();
      thread2.join();
  }

  public void run() {
     if(mc != null) {
        System.out.println("ph not null");
     } else {
        System.out.println("ph null"); // THIS CODE GETS EXECUTED
     }
     // some code
  }
}

当我运行它时,我得到这个输出:

ph not null
ph not null
于 2013-07-20T17:18:45.470 回答