Reputation: 1403
Does anyone knows how to add a test Resource (i.e. one that is only for testing purposes and not added in run() method of the app)?
Here is an example:
public class MyTest {
@ClassRule
public static final DropwizardAppRule<TestConfiguration> RULE =
new DropwizardAppRule<TestConfiguration>(MyApp.class, "my-app-config.yaml");
@BeforeClass
public static void setUpBeforeClass() throws Exception
{
MyTest.RULE.getEnvironment().jersey().register(new JustForTestingResource());
}
@Test
public final void testTestResource()
{
Client client = new Client();
ClientResponse response = client.resource(
String.format("http://localhost:%d/rest/v1/test", RULE.getLocalPort()))
.get(ClientResponse.class);
assertThat(response.getStatus(), is(200));
}
}
and
public class JustForTestingRessource {
@GET
@Path("test")
@Produces(MediaType.APPLICATION_JSON)
public Response getInTestResource()
{
return Response.status(Status.OK).type(MediaType.TEXT_PLAIN).entity("get @Path(\"test\") is ok").build();
}
}
My problem is that the added resource is not added and I get resource not found 404 error response. It seems that I am registering the new resource after resource publishing and there is no refresh inside Dropwizard after start.
I dont want to extend my Application class and I dont want to insert test code into my real application code. Does anyone knows how to register the test resource without registering it in run() method of the Application?
This works, but a new class is needed:
public class TestService extends MyService{
@Override
public void run(
TestConfigurationconfiguration,
Environment environment) throws ClassNotFoundException
{
environment.jersey().register(new JustForTestingRessource());
super.run(configuration,environment);
}
}
Call in JUnit as already known:
@ClassRule
public static DropwizardAppRule<TestConfiguration> RULE =
new DropwizardAppRule<TestConfiguration>(TestService.class, "my-app-config.yaml");
Upvotes: 7
Views: 13858
Reputation: 701
public class TestMain extends Main{
public static void main(String ... args) throws Exception {
new TestMain().run(args);
}
@Override
public void initialize(Bootstrap<AppConfiguration> bootstrap) {
super.initialize(bootstrap);
bootstrap.addBundle(
new MigrationsBundle<AppConfiguration>() {
@Override
public DataSourceFactory getDataSourceFactory(
AppConfiguration configuration) {
return configuration.getDataSourceFactory();
}
});
}
}
Upvotes: 0
Reputation: 1121
I had the similar issue with the @ClassRule, maybe it can help to somebody..
In my test (Groovy) the invocation of RULE.getApplication() or getEnvironment() from @BeforeClass method returned null:
def setupSpec() {
RULE.application.run()
}
shown
java.lang.NullPointerException: Cannot invoke method run() on null object
I.e. RULE.testSupport had both null application and environment.
I found out that the call to RULE.testSupport.before() just before run() solves the error:
def setupSpec() {
RULE.testSupport.before()
RULE.application.run()
}
And then @AfterClass method:
def cleanupSpec() {
RULE.testSupport.after()
}
Or just use @Rule instead of @ClassRule and call
def setup() {
RULE.application.run()
}
inside of @Before method instead of @BeforeClass.
Though It seems strange, maybe there is some other better solution exists..
Upvotes: 0
Reputation: 4789
Edit: Removing previous answer because it didn't solve your problem the way you wanted to do it.
I dug into the environment startup code and realized the reason why registering a controller didn't make it available is because jetty had already been started. If you stop jetty, register your controller and start jetty back up again, your resource will be available and you can use it in your test.
@BeforeClass
public static void setUpBeforeClass() throws Exception
{
MyTest.RULE.environment.applicationContext.stop()
MyTest.RULE.environment.jersey().register(new JustForTestingResource())
MyTest.RULE.environment.applicationContext.start()
}
Upvotes: 5
Reputation: 12003
You can test the Resource itself in a Jersey Container without starting a full dw-instance.
Check the "Testing Resources" section.
import static org.fest.assertions.api.Assertions.assertThat;
import static org.mockito.Mockito.*;
public class PersonResourceTest {
private static final PeopleStore dao = mock(PeopleStore.class);
@ClassRule
public static final ResourceTestRule resources = ResourceTestRule.builder()
.addResource(new PersonResource(dao))
.build();
private final Person person = new Person("blah", "[email protected]");
@Before
public void setup() {
when(dao.fetchPerson(eq("blah"))).thenReturn(person);
// we have to reset the mock after each test because of the
// @ClassRule, or use a @Rule as mentioned below.
reset(dao);
}
@Test
public void testGetPerson() {
assertThat(resources.client().resource("/person/blah").get(Person.class))
.isEqualTo(person);
verify(dao).fetchPerson("blah");
}
}
Upvotes: 2