javajunitnullpointerexceptionjunit5dropwizard

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


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.


Solution

  • 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.