Monday 15 May 2017

Test your Application with the WebLogic Maven plugin

In this blogpost I will show you how easy it is to add some unit tests to your application when you use Maven together with the 12.1.3 Oracle software ( like WebLogic , JDeveloper or Eclipse OEPE).

To demonstrate this, I will create a RESTful Person Service in JDeveloper 12.1.3 which will use the Maven project layout.

We will do the following:

Create a Project and Application based on a Maven Archetype.
Create a JAX-RS 2.0 Person Resource

In the Maven Test phase, we will test this Person Rest Service.
  • Use JerseyTest to test the Person Resource
  • Use JerseyTest and Mockito to test and mock the Person Rest Service.

In the Maven Integration Test phase, we will test the Person Resource on a WebLogic domain and run some external soupUI tests.

  • Create a WebLogic Domain
  • Start the AdminServer
  • Deploy the JAX-RS 2.0 shared library and our Person Rest Service
  • Run some soapUI test cases.
  • Remove the WebLogic domain.

Before we can start, we need to use oracle-maven-sync-12.1.3.jar plugin to populate our local or maven repository with all the Oracle binaries.

For more information how to do this you can take a look at one of the following links.


We start by creating a new application in JDeveloper 12.1.3


Go to the Maven tree and select Generate from Archetype.



 Provide the maven Group and Artifact id and lookup the basic-webservice Archetype.


When you search for webLogic you will find the basic web service archetypes. Make sure you select the 12.1.3 one.


This will create a Web Service Project but we also need to create an application. So the next step is the Application creation dialog.


Because we want to use JAX-RS and not JAX-WS, so we need to delete the SayHello web service.



Next step is adding the REST Web Service feature to this project. 


Create a RESTful Service class



Choose JAX-RS 2.0 Style


Choose RESTful Service From New


 Provide all the REST service details and enable application/json as Media Types.


And viola we got our Person RESTful Service.


JDeveloper will automatically add the JAX-RS 2.0 shared library to your project.



This finishes our basic service.

This is how the final Person service will look like.

package com.example.rest.services;
import com.example.rest.data.PersonDao;
import com.example.rest.data.PersonNotFoundException;
import com.example.rest.entities.Person;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;
@Path("person")
@Consumes("application/json")
@Produces("application/json")
public class PersonResource {
public PersonResource() {
}
PersonDao personDao = new PersonDao();
public void setPersonDao(PersonDao personDao) {
this.personDao = personDao;
}
@GET
public Response getPersons() {
List<Person> persons = personDao.findAll();
return Response.ok(persons.toArray(new Person[persons.size()])).build();
}
@GET
@Path("/{id}")
public Response getPerson(@PathParam("id") Integer id) {
try {
Person person = personDao.findPerson(id);
return Response.ok(person).build();
} catch (PersonNotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).build();
}
}
}
view rawPersonResource.java hosted with ❤ by GitHub
We can now add some unit tests to the Maven Test phase. We will make 2 JUnit test cases where we will use JerseyTest, so we can test the Person Resource and one with Mockito so we can also mock the data of the Person Resource. 

For these tests a lightweight grizzly2 HTTP container will be started by Maven.

The pom's dependency libraries which we will need.

<dependencies>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<version>2.11</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework</groupId>
<artifactId>jersey-test-framework-core</artifactId>
<version>2.11</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.bundles.repackaged</groupId>
<artifactId>jersey-guava</artifactId>
<version>2.11</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-grizzly2-servlet</artifactId>
<version>2.11</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.11</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.11</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.11</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.9.5</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
</dependencies>
view rawpom.xml hosted with ❤ by GitHub
Using only JerseyTest is probably not so meaningful because you probably also need an emulate your EJB's but here you have the JerseyTest snippet

package test.com.example.rest.services;
import com.example.rest.entities.Person;
import com.example.rest.services.PersonResource;
import java.util.List;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import org.junit.Test;
public class PersonResourceTest extends JerseyTest {
public PersonResourceTest() {
}
@Override
protected Application configure(){
return new ResourceConfig(PersonResource.class);
}
@Test
public void findAll() {
final Response result = target("person").request()
.accept(MediaType.APPLICATION_JSON)
.get(Response.class);
if(result.getStatus() != Response.Status.OK.getStatusCode()){
fail("Wrong status code "+result.getStatus());
}
List<Person> persons = result.readEntity(new GenericType<List<Person>>(){});
assertEquals(2,persons.size());
for ( Person person : persons) {
assertNotNull(person.getId());
if ( person.getId() == 1 ) {
assertEquals("Edwin",person.getFirstName());
}
if ( person.getId() == 2 ) {
assertEquals("Mark",person.getFirstName());
}
}
}
@Test
public void findPerson() {
final Response result = target("person/1").request()
.accept(MediaType.APPLICATION_JSON)
.get(Response.class);
if(result.getStatus() != Response.Status.OK.getStatusCode()){
fail("Wrong status code "+result.getStatus());
}
Person person = result.readEntity(new GenericType<Person>(){});
assertEquals("Edwin",person.getFirstName());
}
@Test
public void findPersonNotfound() {
final Response result = target("person/100").request()
.accept(MediaType.APPLICATION_JSON)
.get(Response.class);
assertEquals(result.getStatus(), Response.Status.NOT_FOUND.getStatusCode());
}
}
And the JerseyTest with Mockito snippet.

package test.com.example.rest.services;
import com.example.rest.data.PersonDao;
import com.example.rest.data.PersonNotFoundException;
import com.example.rest.entities.Person;
import com.example.rest.services.PersonResource;
import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.mockito.runners.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class PersonResourceMockTest extends JerseyTest {
public PersonResourceMockTest() {
}
private PersonDao personDao;
@Override
protected Application configure(){
PersonResource personResource = new PersonResource();
personDao = mock(PersonDao.class);
personResource.setPersonDao(personDao);
return new ResourceConfig().registerInstances(personResource);
}
@Test
public void findAll() {
List<Person> mockPersons = new ArrayList<Person>();
mockPersons.add(new Person(1,"John","Doe"));
when(personDao.findAll()).thenReturn(mockPersons);
Response result = target("person").request()
.accept(MediaType.APPLICATION_JSON)
.get(Response.class);
if(result.getStatus() != Response.Status.OK.getStatusCode()){
fail("Wrong status code "+result.getStatus());
}
verify(personDao).findAll();
List<Person> persons = result.readEntity(new GenericType<List<Person>>(){});
assertEquals(1,persons.size());
for ( Person person : persons) {
assertNotNull(person.getId());
if ( person.getId() == 1 ) {
assertEquals("John",person.getFirstName());
}
}
}
@Test
public void findPerson() throws PersonNotFoundException {
Integer id = 10;
Person mockPerson = new Person(id,"John","Doe");
when(personDao.findPerson(id)).thenReturn(mockPerson);
final Response result = target("person/"+id).request()
.accept(MediaType.APPLICATION_JSON)
.get(Response.class);
verify(personDao).findPerson(id);
if(result.getStatus() != Response.Status.OK.getStatusCode()){
fail("Wrong status code "+result.getStatus());
}
Person person = result.readEntity(new GenericType<Person>(){});
assertEquals("John",person.getFirstName());
}
} We can now run mvn clean test


This is nice, but the next question is "Can we also run this Application on a WebLogic Container and do some external tests"

For this we can use the weblogic-maven-plugin in the integration-test Maven phase.
The WebLogic plugin can create a new WebLogic Domain, Start the AdminServer, Deploy the JAX-RS 2 shared library, our Application and off course stop the AdminServer and remove the domain.

<properties>
<project_mdwhome>/Users/edwin/Oracle/JDevMiddleware12.1.3_normal</project_mdwhome>
<project_adminurl>t3://127.0.0.1:7001</project_adminurl>
<project_wlsusername>weblogic</project_wlsusername>
<project_wlspassword>weblogic1</project_wlspassword>
<project_wstarget>AdminServer</project_wstarget>
<project_wsurl>http://127.0.0.1:7001</project_wsurl>
</properties>
<build>
<plugins>
<plugin>
<groupId>com.oracle.weblogic</groupId>
<artifactId>weblogic-maven-plugin</artifactId>
<version>12.1.3-0-0</version>
<configuration>
<middlewareHome>${project_mdwhome}</middlewareHome>
<user>${project_wlsusername}</user>
<password>${project_wlspassword}</password>
<domainHome>${project.build.directory}/base_domain</domainHome>
<adminurl>${project_adminurl}</adminurl>
<targets>${project_wstarget}</targets>
</configuration>
<executions>
<execution>
<id>wls-create-domain</id>
<phase>pre-integration-test</phase>
<goals>
<goal>create-domain</goal>
</goals>
<configuration>
<failOnDomainExists>true</failOnDomainExists>
</configuration>
</execution>
<execution>
<id>wls-start-domain</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start-server</goal>
</goals>
</execution>
<execution>
<id>wls-deploy-jax-rs</id>
<phase>pre-integration-test</phase>
<goals>
<goal>deploy</goal>
</goals>
<configuration>
<source>${project_mdwhome}/wlserver/common/deployable-libraries/jax-rs-2.0.war</source>
<verbose>true</verbose>
<name>jax-rs</name>
<library>true</library>
</configuration>
</execution>
<execution>
<id>wls-deploy</id>
<phase>pre-integration-test</phase>
<goals>
<goal>deploy</goal>
</goals>
<configuration>
<source>${project.build.directory}/${project.build.finalName}.${project.packaging}</source>
<verbose>true</verbose>
<name>${project.build.finalName}</name>
</configuration>
</execution>
<execution>
<id>wls-undeploy</id>
<phase>post-integration-test</phase>
<goals>
<goal>undeploy</goal>
</goals>
<configuration>
<verbose>true</verbose>
<name>${project.build.finalName}</name>
</configuration>
</execution>
<execution>
<id>wls-stop-domain</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop-server</goal>
</goals>
</execution>
<execution>
<id>wls-destroy-domain</id>
<phase>post-integration-test</phase>
<goals>
<goal>remove-domain</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
view rawpom2.xml hosted with ❤ by GitHub
In SoapUI 5.0 I made a Testcase for this Person REST Service and add the soapUI project xml to our JDeveloper project.


The Maven soapUI plugin , In my case I added the smartbear private repository to my own Nexus repository.

<plugin>
<groupId>com.smartbear.soapui</groupId>
<artifactId>soapui-maven-plugin</artifactId>
<version>5.0.0</version>
<configuration>
<projectFile>${project.basedir}/src/main/test/resources/soapui/person-soapui-project.xml</projectFile>
<junitReport>true</junitReport>
<printReport>true</printReport>
<exportAll>true</exportAll>
<testSuite>PersonTestSuite1</testSuite>
<testCase>Persons</testCase>
<endpoint>${project_wsurl}</endpoint>
<outputFolder>${project.build.directory}/soapui</outputFolder>
</configuration>
<executions>
<execution>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
</execution>
</executions>
</plugin>
view rawsoapui.xml hosted with ❤ by GitHub
Now we can start maven with mvn clean deploy

Create a new WebLogic domain ( inside the maven target folder ),  deploy our application together with the shared library.


Start the soapUI testcases.
 

With this as result.


That's all.

No comments:

Post a Comment