Skip to content

@ScenarioState sometimes not injected while running multithreaded under TestNG #239

@adrian-herscu

Description

@adrian-herscu

Using JGiven version 0.11.4 -- my test class looks like:

@Test(singleThreaded=true)
public class Caching extends PegasusRestTest {

    @Test
    public void shouldCacheProduct() {
        given_pegasus_machine_with_cache();

        dukesClientActions
            .when().deleting_key("1999757850_-1_-1");
        ....

It has few other similarly looking methods.

The deleting_key method is implemented as follows:

public class PegasusDukesClientActions<SELF extends PegasusDukesClientActions<SELF>>
    extends GenericActions<DukesClient, SELF> {

    @ExpectedScenarioState
    protected ThreadLocal<CacheConfiguration> targetDukesConfiguration;

    public SELF deleting_key(final String key) {
        log.debug("deleting key {}", key); //$NON-NLS-1$
        log.trace("targetDukesConfiguration = {}", targetDukesConfiguration);
        try (val dukesClient = new DukesClientWrapper<>(
            new InflateDeflateTranscoder(), targetDukesConfiguration.get())) {  <<<--- NPE here
            dukesClient.delete(key);
        .....

The targetDukesConfiguration is initialized like this:

public class PegasusDukesClientFixtures<SELF extends PegasusDukesClientFixtures<SELF>>
    extends GenericFixtures<DukesClient, SELF> {

    @ProvidedScenarioState
    protected final ThreadLocal<CacheConfiguration> targetDukesConfiguration =
        new ThreadLocal<>();

    public SELF a_Dukes_cache_at(final URI url, final int timeoutMs) {
        log.debug("target Dukes cache at {}", url); //$NON-NLS-1$
        targetDukesConfiguration.set(new CacheConfiguration() {
            {
                setHostsAndPorts(url.toString());
        .....

Hence I expect in the PegasusDukesClientActions stage to have targetDukesConfiguration initialized at least with a new empty ThreadLocal.

However, when I am setting @test(singleThreaded=false) on Caching class I am sporadically getting a NullPointerException when accessing targetDukesConfiguration in the deleting_key method implementation above.

Here is a log with just two test methods:

11:37:52.246 [DEBUG] [pool-1-thread-2]: PegasusDukesClientFixtures - target Dukes cache at http://somewhere/pools/productservicecache
11:37:52.263 [DEBUG] [pool-1-thread-1]: PegasusDukesClientFixtures - target Dukes cache at http://somewhere/pools/productservicecache
......
......
11:37:53.980 [DEBUG] [pool-1-thread-2]: PegasusDukesClientActions - deleting key 1510742630_-1_-1
11:37:53.980 [TRACE] [pool-1-thread-2]: PegasusDukesClientActions - targetDukesConfiguration = null
.....
11:37:54.043 [DEBUG] [pool-1-thread-1]: PegasusDukesClientActions - deleting key 1999757850_-1_-1
11:37:54.044 [TRACE] [pool-1-thread-1]: PegasusDukesClientActions - targetDukesConfiguration = null

Sometimes it works, but most of the times it does not. Easy to reproduce :)

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions