Acceptance testing a Dropwizard app with Cucumber

Csaba Palfi, Mar 2014

Dropwizard is a 'damn simple library for building production-ready RESTful web services'. It's an opininated selection of a number of lightweight Java libraries and wonderful for building microservices. The ThoughtWorks Tech Radar now also has it in it's adopt circle.

I'm also a big fan of BDD and love Cucumber and it's version on the JVM. It's not just a test framework but more of a collaboration tool. That's one of the reasons why I much prefer it to just writing acceptance tests with JUnit.

Dropwizard provides some great testing tools. It comes with a nice JUnit Rule named DropwizardAppRule (previously DropwizardServiceRule). If you write your acceptance tests with JUnit you can start/stop your app with the provided rule. You can mock your REST dependencies with WireMock which also has a JUnit rule. What if you want the something similar but with Cucumber?

No Cucumber global hooks

The first problem is that Cucumber-JVM and Cucumber has no support for hooking in a setup/teardown step before/after all your feature files are ran. It currently only supports @Before/@After hooks which run the annotated methods before/after each scenario. The workaround for this is described in detail in cucumber-jvm#515 and involves adding a static field to your StepDefs class and adding shutdownHook).

Based on cucumber-jvm#672 and cucumber-jvm#678 we're getting @BeforeAll and @AfterAll hooks in an upcoming release.

DropwizardAppRule is JUnit only

The second issue is that DropwizardAppRule is tied to JUnit and doesn't expose it's start/stop methods. Even if you run your Cucumber tests with JUnit you need functionality (port, environment, etc) from this rule in your StepDefs class so it's not likely to help.

I'm generalizing DropWizardAppRule in dropwizard#488 to enable support for test frameworks other than JUnit and Scala support as well. Whatch the issue if you're interested but it's going to be merged sometime after 0.7.0.

Solution for now

In the meantime you can create your own DropwizardTestSupport class and have to use the hack instead of @BeforeAll.

You should end up with something like this in your StepDefs class:

private static DropwizardTestSupport<ExampleConfiguration> service;

@Before
public void setUp() throws Exception {
    if(service==null){
        service = new DropwizardTestSupport(ExampleService.class,
                Resources.getResource("test.yml").getPath());
        service.startIfRequired();
        //Hack until @BeforAll is properly supported by Cucumber-JVM
        Runtime.getRuntime().addShutdownHook(new Thread(){
            @Override
            public void run() {
                service.stop();
            }
        });
    }
}

This worked for me perfectly fine.