The simplest “micro” deployment (ArqTip #2)

read the asciidoc based version of this post here.

The second Arquillian tip is the simplest “micro” deployment. Its a Arquillian deployment that uses the hole project as deployment with no need for adding individual classes, packages or libraries:

simplest-deployment

@RunWith(Arquillian.class)
public class SimplestDeployment {

    @Deployment
    public static Archive<?> createDeployment() {
        WebArchive war = ShrinkWrap.create(ZipImporter.class, "cdi-crud.war").
                importFrom(new File("target/cdi-crud.war")).as(WebArchive.class);
        war.addAsResource("persistence.xml", "META-INF/persistence.xml");//replace with test persistence
        return war;
    }

    @Inject
    CarService carService;


    @Test
    @UsingDataSet("car.yml")
    public void shouldCountCars() {
        assertNotNull(carService);
        assertEquals(carService.crud().count(), 4);
    }
}

This basically uses a previously builded project as deployment and just replaces its persistence.xml to use a test database.

Compare it with a traditional deployment here.

Of course that this simplicity comes with a price:

1 – Its not a true micro deployment because it uses the hole application. If your application is big the deployment can take considerable time(seconds);

2 – You need to build the application before running the test. Here you lose a big advantage of Arquillian which is to not build the application if a test (even functional tests) has failed.

To overcome problem #2 you can execute the tests in surefire integration-tests phase:

<profile>
    <id>simple-deployment</id>
    <build>
        <plugins>
            <plugin>
                <artifactid>maven-surefire-plugin</artifactid>
                <version>2.16</version>
                <executions>
                    <execution>
                        <id>after-package</id>
                        <phase>integration-test</phase>
                        <goals>
                            <goal>test</goal>
                        </goals>
                        <configuration>
                            <skiptests>false</skiptests>
                            <includes>
                                <include>**/*SimplestDeployment.java</include>
                            </includes>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</profile>

There is an issue from 2012 in Arquillian issue tracker which address this feature of a “simplest deployment”  using a single annotation , see the issue here: https://issues.jboss.org/browse/ARQ-74.

Source code of this post can be found here: https://github.com/rmpestano/cdi-crud/blob/cdi-crud-universe/src/test/java/com/cdi/crud/it/SimplestDeployment.java

 

Test your REST endpoints inside the container (ArqTip #1)

 

read the asciidoc based version of this post here.

 

Since Arquillian 1.1.9.Final it is possible to get deployment URL even in in-container tests. This enables REST endpoints testing inside the container.

The main advantage of running this kind of test inside the container (same JVM) is that you can call any service/method of your application before making the (test)rest call.

Even better, you can prepare your database or whatever configuration you need before running the test. Here is an example using arquillian persistence (which doesn’t work outside the container – see Arq1077):

 

 

@RunWith(Arquillian.class)
public class CrudRestIt {

    @Deployment(name = "cdi-rest.war")
    public static Archive<?> createDeployment() {
        WebArchive war = Deployments.getBaseDeployment();
        MavenResolverSystem resolver = Maven.resolver();
        war.addAsLibraries(resolver.loadPomFromFile("pom.xml").resolve("com.jayway.restassured:rest-assured").withTransitivity().asFile());
        war.addAsLibraries(resolver.loadPomFromFile("pom.xml").resolve("com.google.code.gson:gson:2.4").withoutTransitivity().asSingleFile());
        System.out.println(war.toString(true));
        return war;
    }

    @ArquillianResource
    URL basePath;


    @Test
    @UsingDataSet("car.yml")
    public void shouldListCars() {
        given().
                queryParam("start", 0).queryParam("max", 10).
        when().
                get(basePath + "rest/cars").
        then().
                statusCode(Status.OK.getStatusCode()).
                body("", hasSize(4)).//dataset has 4 cars
                body("model", hasItem("Ferrari")).
                body("price", hasItem(2450.8f)).
                body(containsString("Porche274"));
    }

}

Note that I have included two libs into the deployment, RestAssured and Gson because both are used inside the test.

As a bonus you can get code coverage of your REST endpoints, something you don’t have when running as client (testable=false a.k.a blackbox):

 

cov

cov2

 

Test source code can be found here: https://github.com/rmpestano/cdi-crud/blob/cdi-crud-universe/src/test/java/com/cdi/crud/it/CrudRestIt.java