【问题标题】:Passing a thread local variable to JUnit test将线程局部变量传递给 JUnit 测试
【发布时间】:2015-03-10 04:25:02
【问题描述】:

我有一个线程,它初始化一个线程局部类变量并开始运行单元测试:

public class FooThread extends Thread {
    TestRunner runner;
    Foo foo;

    public void run() {
        initSomeThreadLocalStuff(); // inits foo and runner
        runner.runJUnitTests(); // JUnitCore.runTest(TestClass)
    }

    private void initSomeThreadLocalStuff() {
        foo = new Foo(this);
        // ...
    }
}

public class Foo() {
    public Foo(FooThread t) {
        // ...
    }    
}

现在我想通过访问(或引用)线程本地对象foo 来运行 JUnit 测试。这可能吗?我尽量保持简单,但复杂的事情似乎不清楚(所以我添加了一些代码):Foo 对象需要初始化当前的FooThread

【问题讨论】:

    标签: java junit thread-local parameterized-unit-test


    【解决方案1】:

    看起来 JUnit parameterized unit tests 是您正在寻找的东西。

    编辑:基于 JUnit wiki 上提供的示例的示例代码:

    @RunWith(Parameterized.class)
    public class Test {
    
        @Parameters
        public static Collection<Object[]> data() {
            return Arrays.asList(new Object[][] {{ new ThreadLocalProvider() }});
        }
    
        @Parameter(value = 0) // first data value (0) is default
        public /* NOT private */ ThreadLocalProvider tloProvider;
    
        public ThreadLocal<Object> tlo;
    
        @Before
        public void setup() {
            // getNew() will be called in the same thread in which the unit test will run.
            tlo = tloProvider.getNew();
        }
    
        @Test
        public void test() {
            // Test using tlo.
        }
    }
    
    class ThreadLocalProvider {
        public ThreadLocal<Object> getNew() {
            // Instantiate a *new* ThreadLocal object and return it.
        }
    }
    

    注意:如果您使用提供程序,您也可以在不使用参数化运行程序的情况下运行测试(只需在 @Before 方法中从提供程序获取一个新对象),但因为我对您的代码了解不多或要求,我会把选择权留给你。

    另外,您不需要实例化您自己的 JUnit Runner。您可以使用 JUnit (reference) 提供的 Runner 以及 @RunWith 注释。

    【讨论】:

    • 我插入了一些一开始可能不清楚的重要代码部分,我认为您的解决方案不适用于我的问题。 tlo 将需要对当前 MyThread 的引用进行初始化。
    • 您可以随意实例化tlo(甚至在测试类或data() 方法之外。data() 方法返回的Collection 也可以由另一个类/实例。
    • 它需要在测试运行的同一线程中实例化。
    • 我不熟悉 Javas ThreadLocal 但您的答案中的 MyThread 在哪里?没有或没有 MyThread,您无法创建 ThreadLocalObject。
    • 请阅读:docs.oracle.com/javase/7/docs/api/java/lang/ThreadLocal.html。每个 Java 代码都将在某个线程中运行 - ThreadLocal 变量将绑定到实例化它的线程(因此得名)。 ThreadLocals 不需要显式包装在 ThreadRunnable 对象中。 @Before 方法将在每个 @Test 方法之前运行,因此在 @Before 中创建的任何 ThreadLocal 变量都将在单元测试的线程中创建。请阅读 JUnit 的 @Before 注释。
    【解决方案2】:

    不知道为什么需要threadLocal。如果您需要使用不同的参数运行相同的测试,那么只需创建这些参数的列表并使用参数化测试(junit 的本机或许多库,如 zohhak 或 junit-dataprovider)。

    如果出于任何原因您需要在测试中访问本地线程,那么您还需要在测试中向其插入数据,因为在运行测试之前您不知道将使用哪个线程来运行测试。但似乎您仍然可以编写一个测试来检查您的代码是否正确使用 threadLocal,然后参数化测试以检查您的代码是否正确处理从 threadLocal 获取的值

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-07
      • 1970-01-01
      • 2017-01-14
      相关资源
      最近更新 更多