November 17, 2017

Making Reusable JUnit Setup with TestRule and @Rule

In the below JAX-RS test we can extract the setup code to a reusable JUnit TestRule class.

public class EmployeeRestIT {
    private Client client;
    private WebTarget target;
    
    @Before
    public void setUp() throws Exception {
        client = ClientBuilder.newClient();
        target = client.target("http://localhost:8080/example-javaee7/rest/employee");
    }
...
}

And the JUnit TestRule class.

package se.magnuskkarlsson.example.javaee7;

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;

public class JaxRSClientTestRule implements TestRule {

    private final Client client;
    private final WebTarget target;

    private JaxRSClientTestRule(String uri) {
        client = ClientBuilder.newClient();
        target = client.target(uri);
    }

    public final static JaxRSClientTestRule buildWithUri(String uri) {
        return new JaxRSClientTestRule(uri);
    }
    
    public Client client() {
        return client;
    }
    
    public WebTarget target() {
        return target;
    }
    
    @Override
    public Statement apply(Statement base, Description description) {
        return new Statement() {

            @Override
            public void evaluate() throws Throwable {
                base.evaluate();
                client.close();
            }
        };
    }

}

And to use the JUnit TestRule class in our JUnit test class.

package se.magnuskkarlsson.example.javaee7.boundary;

import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import javax.ws.rs.client.Entity;
import static javax.ws.rs.core.MediaType.*;
import javax.ws.rs.core.Response;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import org.junit.Rule;
import org.junit.Test;
import se.magnuskkarlsson.example.javaee7.JaxRSClientTestRule;
import static se.magnuskkarlsson.example.javaee7.JaxRSClientTestRule.buildWithUri;

public class EmployeeRestIT {
    
    @Rule
    public JaxRSClientTestRule rule = buildWithUri("http://localhost:8080/example-javaee7/rest/employee");

    @Test
    public void crud() throws Exception {
        JsonObjectBuilder builderCreate = Json.createObjectBuilder();
        JsonObject input = builderCreate.add("name", "Foo Bar").build();
        Response respCreate = rule.target().request(APPLICATION_JSON).post(Entity.json(input));
        assertThat(respCreate.getStatus(), is(201));
        String location = respCreate.getHeaderString("Location");
        assertNotNull(location);

        Response respGet = rule.client().target(location).request(APPLICATION_JSON).get();
        assertThat(respGet.getStatus(), is(200));
        JsonObject payload = respGet.readEntity(JsonObject.class);
        System.out.println("payload='" + payload + "'");
        
        int id = payload.getInt("id");
        JsonObjectBuilder builderUpdate = Json.createObjectBuilder();
        JsonObject update = builderUpdate.add("id", id).add("name", "UPDATED!").build();
        Response respUpdate = rule.target().request(APPLICATION_JSON).put(Entity.json(update));
        assertThat(respCreate.getStatus(), is(201));
        System.out.println("respUpdate=" + respUpdate.readEntity(JsonObject.class));
        
        Response respDelete = rule.target().path("/" + id).request(APPLICATION_JSON).delete();
        assertThat(respDelete.getStatus(), is(204));
    }
}

No comments: