1

I have a thread which inits a thread local class variable and starts with running unit tests:

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) {
        // ...
    }    
}

Now I want to run the JUnit tests with access (or a reference) to the thread local object foo. Is this possible? I tried to keep it simple but the complicated thing seemed not to be clear (so I added some code): the Foo object needs the current FooThread to be initialized.

kryger
  • 12,906
  • 8
  • 44
  • 65
Gobliins
  • 3,848
  • 16
  • 67
  • 122

2 Answers2

0

Looks like JUnit parameterized unit tests is what you're looking for.

Edit: Sample code based on the example provided on the 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.
    }
}

Note: If you use a provider, you can run your tests without using the Parameterized runner as well (just get a new object from the provider in the @Before method) but since I don't know much about your code or requirement, I'll leave that choice to you.

Also, you don't need to instantiate your own JUnit Runner. You can use a Runner provided by JUnit (reference) along with the @RunWith annotation.

nhylated
  • 1,575
  • 13
  • 19
  • I inserted some important code parts which may have not be clear at first, your solution i think will not work with my problem. tlo will need a reference to the current MyThread to be initialized. – Gobliins Jan 12 '15 at 12:30
  • You can instantiate `tlo` anyway you like (and even outside the test class or the `data()` method. The `Collection` returned by the `data()` method can also be generated by another class/instance. – nhylated Jan 12 '15 at 12:41
  • It needs to be instantiated within the same thread as the tests run. – Gobliins Jan 12 '15 at 12:55
  • I am not familiar with Javas ThreadLocal but where is MyThread in your answer? You can not create a ThreadLocalObject without or out of MyThread. – Gobliins Jan 12 '15 at 13:17
  • Please read: http://docs.oracle.com/javase/7/docs/api/java/lang/ThreadLocal.html. Every Java code will run in some thread - the ThreadLocal variable will be bound to the thread in which it is instantiated (hence the name). ThreadLocals don't need to be explicitly wrapped inside a `Thread` or `Runnable` object. The `@Before` method will run before each `@Test` method so any ThreadLocal variable created in `@Before` will be created in the unit test's thread. Please read-up on JUnit's `@Before` annotation too. – nhylated Jan 12 '15 at 13:20
  • Show me your implementation of the getNew() Method. I changed name MyThread to FooThread and ThreadLocalObject to Foo – Gobliins Jan 12 '15 at 13:30
0

no idea why do you need threadLocal. if you need run same tests with different parameters then just create a list of those parameters and use parameterized tests (junit's native or of many libraries like zohhak or junit-dataprovider).

if for any reason you need to access thread local inside your tests then you also need to insert data to it inside the test because before running tests you don't know what thread will be used to run the test. but still it seems like you can write one tests to check if your code correctly uses threadLocal and then parameterized tests to check if your code correctly handles value taken from threadLocal

piotrek
  • 13,982
  • 13
  • 79
  • 165