java.lang.NullPointerException at io.dropwizard.testing.junit5.DropwizardExtensionsSupport.beforeEach

Viewed 571

I am trying to test a Dropwizard resource.

My test looks like this:

@ExtendWith(DropwizardExtensionsSupport.class)
public class CommonObjectsTest {
    private ResourceExtension EXT;

    @BeforeEach
    public void setup() {
        ApplicationConfig applicationConfig = mock(ApplicationConfig.class);
        when(applicationConfig.getYears()).thenReturn(1);

        MyAppConfig myAppConfig = mock(MyAppConfig.class);
        when(myAppConfig.getAppConfig()).thenReturn(applicationConfig);

        EmailClient emailClient = mock(EmailClient.class);
        CommonObjects commonObjects = new CommonObjects(myAppConfig, emailClient);

        EXT = ResourceExtension.builder()
                .addResource(commonObjects)
                .build();
    }

    @Test
    public void getYearsSuccessfully() {
        Response response = EXT.target("/get_years").request().get();
        System.out.println(response);
    }
}

However, this gives the error message:

java.lang.NullPointerException
    at io.dropwizard.testing.junit5.DropwizardExtensionsSupport.beforeEach(DropwizardExtensionsSupport.java:123)
    at io.dropwizard.testing.junit5.DropwizardExtensionsSupport.beforeEach(DropwizardExtensionsSupport.java:106)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeBeforeEachCallbacks$1(TestMethodTestDescriptor.java:159)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeBeforeMethodsOrCallbacksUntilExceptionOccurs$5(TestMethodTestDescriptor.java:195)
    ...

which is frankly uninformative. Can someone point out what is wrong here?

P/S Here is the CommonObjects constructor:

    public CommonObjects(MyAppConfig configuration, EmailClient emailClient) {
        ApplicationConfig appConfig = configuration.getAppConfig();
        this.years = appConfig.getYears();
        this.emailClient = emailClient;
    }

which also explains why I am creating the resource extension before each test case.

2 Answers

In the end, instead of using mocks, I created stubs extending from concrete classes.

For example, for ApplicationConfig, I created ApplicationConfigStub:

public class ApplicationConfigStub extends ApplicationConfig {
    @Override
    public int getYears() {
        return 1;
    }
}

And for MyAppConfig, I created MyAppConfigStub:

public class MyAppConfigStub extends MyAppConfig {
    @Override
    public ApplicationConfig getAppConfig() {
        return new ApplicationConfigStub();
    }
}

Then, I used these stubs when initialising the ResourceExtension in the test class:

private static final EmailClient emailClient = mock(EmailClient.class);
private static final ResourceExtension EXT = ResourceExtension.builder()
            .addResource(new CommonObjects(new MyAppConfigStub(), emailClient))
            .build();

This would allow for the resource extension to be initialised at declaration even if we are calling methods in other dependencies during the initialisation.

This may not be the solution to this answer, however I had a similar exception with the bonehead problem of running the extension in vintage JUnit rather than Jupiter which is required for the ExtendWith annotation. Maybe this will save someone an hour or two.

NullPointerException:

import org.junit.Test;

Works:

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
Related