How to use WireMock for stubbing web services

WireMock is a library for stubbing and mocking REST Web services. This will be a handy one if we want to test external web services. When we use this, it will start a mock http server on the given port number so it looks like we are connecting to the actual web services.

Lets see how we can use this for writing JUnit test cases. Consider that you have two web services. one if for creating the user and another one is for fetching it. We don’t worry about the actual services. Let’s see how we can stub these services with WireMock.

I am going to use JUnit Rule for this example. Add the below dependencies in the maven pom.xml file.


<dependencies>
        <dependency>
            <groupId>com.github.tomakehurst</groupId>
            <artifactId>wiremock</artifactId>
            <version>2.7.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.core</groupId>
            <artifactId>jersey-client</artifactId>
            <version>2.18</version>
        </dependency>
        <dependency>
            <groupId>org.hamcrest</groupId>
            <artifactId>hamcrest-all</artifactId>
            <version>1.3</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>

Now my test code is given below,


package com.wiremock;

import com.github.tomakehurst.wiremock.junit.WireMockRule;
import org.glassfish.jersey.client.JerseyClient;
import org.glassfish.jersey.client.JerseyClientBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;

import javax.ws.rs.core.Response;

import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.get;
import static com.github.tomakehurst.wiremock.client.WireMock.matching;
import static com.github.tomakehurst.wiremock.client.WireMock.post;
import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor;
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching;
import static javax.ws.rs.client.Entity.entity;
import static javax.ws.rs.core.MediaType.APPLICATION_XML_TYPE;
import static org.junit.Assert.assertEquals;

public class WireMockTest {

    @Rule
    public WireMockRule rule = new WireMockRule(8080);

    private static String GET_USERS = "http://localhost:8080/users/12345";
    private static String POST_USER = "http://localhost:8080/users";
    private static String USER_CONTENT = "12345bala";

    JerseyClient client;

    @Before
    public void setUp() {
        client = JerseyClientBuilder.createClient();
    }

    @After
    public void tearDowm() {
        rule.shutdown();
    }

    private void stubFor(){
      rule.stubFor(post(urlEqualTo("/users")).willReturn(aResponse().withStatus(200));
rule.stubFor(get(urlEqualTo("/users/12345")).willReturn(
                aResponse().withHeader("Content-Type", "application/xml")
                        .withBody(USER_CONTENT)));
    }

    @Test
    public void testAddUser() {
        stubFor();
        client.target(POST_USER).request().post(entity(USER_CONTENT, APPLICATION_XML_TYPE));
        rule.verify(postRequestedFor(urlMatching("/users"))
                            .withRequestBody(matching(USER_CONTENT))
                            .withHeader("Content-Type", matching("application/xml")));

    }

    @Test
    public void testGetUser() {
        stubFor();
        Response response = client.target(GET_USERS).request().get();
        String output = response.readEntity(String.class);
        System.out.println("output: "+output);
        assertEquals(200, response.getStatus());
        assertEquals(USER_CONTENT, output);
    }
}

Explanation:
The first step is to add the WireMockRule and pass the port number on which the mock server is going to be run. You can specify any port number. By default its 8080.

Now the next step is to add the stubFor for both services(getUser, addUser)
For adding user service, the method is POST and it will return the response status as 200. For getting the user service, the method is GET and it will the return the static user response XML.

The next step is to call the services with the REST client object.
The final step is to do the verification. We can do the same kind of verification as such verifying the actual response.

Refer the code @https://github.com/dkbalachandar/java-wiremock-tester

Java 8 – Lambda Predicates

Predicate is a functional interface in java 8. It’s used to hold the lambda expression and takes a value or an object and return a boolean value.

This is very handy if you want to do any validation or filtering anythig.

Refer the below example to know how to use the Predicate for validating the number whether it’s even or not and some more operations.


import java.util.function.Predicate;

public class PredicateMain {

    public static void main(String[] args) {
        // Validate whether the number is even or not.
        System.out.println("Predicates.isEven(2)::" + Predicates.isEven().test(2));
        // Validate whether the number is odd or not.
        System.out.println("Predicates.isOdd(3) ::" + Predicates.isOdd().test(3));
        // Validate whether the number is even and also greater than 100
        System.out.println("Predicates.isEven().and(Predicates.isGreaterThan100(100)) ::"
                + Predicates.isEven().and(Predicates.isGreaterThan100()).test(100));
        // Validate whether the number is even and also greater than 100
        System.out.println("Predicates.isEven().and(Predicates.isGreaterThan100(102)) ::"
                + Predicates.isEven().and(Predicates.isGreaterThan100()).test(102));
        // Validate whether the number is even or greater than 100
        System.out.println("Predicates.isEven().or(Predicates.isGreaterThan100(101)) ::"
                + Predicates.isEven().or(Predicates.isGreaterThan100()).test(101));
        // Validate whether the number is even and negate the result.
        System.out.println("Predicates.isEven().negate(11) ::" + Predicates.isEven().negate().test(11));
    }

    static class Predicates {

        public static Predicate isEven() {
            return number -> number % 2 == 0;
        }

        public static Predicate isOdd() {
            return number -> number % 2 != 0;
        }

        public static Predicate isGreaterThan100() {
            return number -> number > 100;
        }
    }
}


Output:



Predicates.isEven(2)::true
Predicates.isOdd(3) ::true
Predicates.isEven().and(Predicates.isGreaterThan100(100)) ::false
Predicates.isEven().and(Predicates.isGreaterThan100(102)) ::true
Predicates.isEven().or(Predicates.isGreaterThan100(101)) ::true
Predicates.isEven().negate(11) ::true


Refer the below example to know how we can use this for filtering


import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class PredicateCollections {

    public static void main(String[] args) {

        List users = Arrays.asList(new User("Bob", 51, 170), new User("john", 52, 80), new User("paul", 45 ,120), new User("alex", 46, 150), new User("scott", 56, 150));

        //All the users whose age are above 50
        List above50Users = filter(users, isAgeAbove50());
        System.out.println("The above 50 age users \n" + above50Users);

        //All the users whose age are below 50
        List below50Users = filter(users, isAgeBelow50());
        System.out.println("The below 50 age users \n"+ below50Users);

        //We can also use the negate expression. Lets see how we can do that
        above50Users = filter(users, isAgeBelow50().negate());
        System.out.println("The above 50 age users \n" + above50Users);

        below50Users = filter(users, isAgeAbove50().negate());
        System.out.println("The below 50 age users \n"+ below50Users);

        //Users whose age is above 50 and weight is more than 100
        List above50AndExcessWeightUsers = filter(users, isAgeAbove50().and(isWeightGtThan100()));
        System.out.println("The above 50 and excess weight users \n"+ above50AndExcessWeightUsers);
    }

    public static Predicate isAgeAbove50() {
        return user -> user.age > 50;
    }

    public static Predicate isAgeBelow50() {
        return user -> user.age < 50;
    }
    public static Predicate isWeightGtThan100() {
        return user -> user.weight > 100;
    }

    public static List filter(List users, Predicate p) {
        return users.stream().filter(p::test).collect(Collectors.toList());
    }

    static class User {

        String name;
        int age;
        int weight;

        User(String name, int age, int weight) {
            this.name = name;
            this.age = age;
            this.weight = weight;
        }

        @Override
        public String toString() {
            return "name:"+name +" age:"+age + " weight:"+weight;
        }
    }
}

Output:


The above 50 age users 
[name:Bob age:51 weight:170, name:john age:52 weight:80, name:scott age:56 weight:150]
The below 50 age users 
[name:paul age:45 weight:120, name:alex age:46 weight:150]
The above 50 age users 
[name:Bob age:51 weight:170, name:john age:52 weight:80, name:scott age:56 weight:150]
The below 50 age users 
[name:paul age:45 weight:120, name:alex age:46 weight:150]
The above 50 and excess weight users 
[name:Bob age:51 weight:170, name:scott age:56 weight:150]


Jersey REST service and Thread Local usage

In this exercise, I am going to provide an example to show how we can use the ThreadLocal with the Jersey REST service.

Consider that it’s a REST application and we need the user details in the application flow many places. The User details will be retrieved with the header information availbale in the HttpServletRequest.
One solution is to pass the HttpServletRequest object whereever its required. But its a tedious job.
So an another way is to use the ContainerRequestFilter and processes the request, then extract out the header and call the back end to get the User details and put into the ThreadLocal storage so that it can be accessible anywhere in that thread flow.

Refer the below sample code to know how to do that. We don’t use the Spring Framework here.

DataHolder:
This class holds the static ThreadLocal variable and it has getter and setter for User object. We will be setting the User Object from the ContainerRequestFilter


package com.utils;

public class DataHolder{

    private static final ThreadLocal userThreadLocal = new ThreadLocal();

    public static void setUser(User user) {
        userThreadLocal.set(user);
    }

    public static User getUser() {
        return userThreadLocal.get();
    }

    public static void remove() {
        userThreadLocal.remove();
    }
}

UserDataCaptureRequestFilter
This filter will intercept the request and extract out the header and retrieve the user details and put it into the ThreadLocal.



package com.filters;

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.core.Context;
import javax.ws.rs.ext.Provider;
import java.io.IOException;

@Provider
public class UserDataCaptureRequestFilter implements ContainerRequestFilter {
    @Context
    private HttpServletRequest httpRequest;

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        //Get the User data from the back end system with the request header/cookie. I have not given the getUser() method but assume it will get the user details 
        User user = getUser(httpRequest);
        DataHolder.setUser(user);
    }
}


Application
The ResourceConfig class where we can specify the packages to look into for the end points and context


public class Application extends ResourceConfig {
    public Application() {
        packages(true, "com.resource");
        packages(true, "com.filters");
    }
}

 
UserResource
This service returns the User details in JSON format. Here We have not retrived the User Details once again since we already retrieved the data in the filter itself. So the data would be available in the Thread scope. So we could use it


package com.resource;

import com.utils.DataHolder;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

@Path("user")
public class UserResource{

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Response getUser() {
       
        return Response.ok().entity(DataHolder.getUser()).type(MediaType.APPLICATION_JSON).build();
    }
}

 

 

Finding the majority Element with Moore’s Voting Algorithm

Leetcode problem:

https://leetcode.com/problems/majority-element/description/

Problem Description:

Given an array of size n, find the majority element. The majority element is the element that appears more than ⌊ n/2 ⌋ times.

You may assume that the array is non-empty and the majority element always exists in the array.

Algorithm Link:

https://www.cs.utexas.edu/~moore/best-ideas/mjrty/index.html

moores-voting-algorithm

Solution:


public class Main {

    public static int majorityElement(int[] nums) {

        int currentElement = 0;
        int counter = 0;
        for (int num : nums) {
            if (counter == 0) {
                currentElement = num;
                counter = 1;
            }
            else {
                if (num == currentElement) {
                    counter++;
                }
                else {
                    counter--;
                }
            }
        }
        return currentElement;
    }

    public static void main(String[] args) {

        int[] nums = new int[] { 1, 3, 4, 5, 5, 1, 1 };
        System.out.println(majorityElement(nums));
    }
}


HK2 Dependency Injection – Using Iterable provider

HK2 is a light weight, dynamic dependency injection framework. If you don’t want to rely on spring framework for managing the dependencies then you can use this.

In this post, I am going to explain how to use the Iterable provider with an example.

Assume that you have a Jersey REST application and it has an endpoint which is responsible for sending out some details to different systems such as Kafka, Database. There is a class called Emitter which is responsible for emitting the data. There are two classes KafkaProducer which produce the data to Kafka and another one DatabaseProducer which writes the data into DB and both these classes implement the MessageProducer interface.

I am not going to give the exact code to be used for doing this. My main motive is to show how we can use Iterable provider here.

MessageProducer.java


public interface MessageProducer {
    public void produce(String message);
}

DBProducer.java
DBProducer class sends out the message to DB


public class DBProducer implements MessageProducer {

    @Override
    public void produce(String message) {
        //Write code to send out the message to DB
        System.out.println("Producing the message to DB");
    }
}

KafkaProducer.java
KafkaProducer class sends out the message to Kafka



public class KafkaProducer implements MessageProducer {

    @Override
    public void produce(String message) {
        //Write code to send out the message to kafka
        System.out.println("Producing the message to Kafka");
    }
}

DependencyBinder.java
DependencyBinder class to be used for binding. Hence you need to pass this class as an init parameter to the Jersey servlet(Parameter name: javax.ws.rs.Application)


import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.server.ResourceConfig;

import javax.inject.Singleton;

public class DependencyBinder extends ResourceConfig {

    public DependencyBinder() {
       //the resource class is available in com/resource folder
        packages(true, "com.resource");
        register(new AbstractBinder() {
            @Override
            protected void configure() {
                bind(Emitter.class).to(Emitter.class).in(Singleton.class);
                bind(KafkaProducer.class).to(MessageProducer.class).in(Singleton.class);
                bind(DBProducer.class).to(MessageProducer.class).in(Singleton.class);
            }
        });
    }

 

Finally the Emitter class. This class has to send the message to different systems. So we can’t inject the each class here. We can use IterableProvider to achieve this. So the HK2 framework gets all the classes which implement the interface MessageProducer and injects into this class. In this example, it will return DBProducer and KafkaProducer instances.


import org.glassfish.hk2.api.IterableProvider;

import javax.inject.Inject;

public class Emitter {

    @Inject
    private IterableProvider<MessageProducer> messageProducers;

    public void emitMessage() {

        // Write code to prepare the message
        String message = "Its a new message";
        for (MessageProducer messageProducer : messageProducers) {
            messageProducer.produce(message);
        }
    }
} 

Testing the mail functionality with Fake Smtp Server

In this post, I am going to show how we can integrate the FakeSmtp server with a java application.

Fake SMTP is a dummy SMTP server which is mainly used for testing the emails. It’s useful for the developers as it emits the email content into a local file directory. So we can check the local file content and do the validations.

The Dockerfile for the Fake Smtp is given below,

mail-rest-docker/tree/master/fake-smtp


FROM java:8

RUN mkdir -p /opt && \
  wget -q http://nilhcem.github.com/FakeSMTP/downloads/fakeSMTP-latest.zip && \ 
   unzip fakeSMTP-latest.zip -d /opt && \
   rm fakeSMTP-latest.zip

VOLUME /output

RUN chmod +x /opt/fakeSMTP-2.0.jar

EXPOSE 25

CMD java -jar /opt/fakeSMTP-2.0.jar --start-server --background --output-dir /output --port 25

If you refer the last line of the above file, you can understand that the email content would be written under the /output folder. So we have to mount the local directory accordingly in the docker compose file.

Next one is the REST application code to send out the email to Fake SMTP server.

mail-rest-docker/blob/master/src/main/java/com/resource/MailResource.java


package com.resource;

import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.Properties;

@Path("/sendMail")
public class MailResource {

    Properties properties = System.getProperties();

    public MailResource() {
        properties.put("mail.smtp.host", System.getenv("SMTP_HOST"));
        properties.put("mail.smtp.port", "25");
    }

    @GET
    @Produces(MediaType.TEXT_HTML) public Response sendSimpleHelloMail() throws WebApplicationException {

        String to = "test123@gmail.com";
        String from = "test123@gmail.com";
        Session session = Session.getDefaultInstance(properties);
        try {
            MimeMessage message = new MimeMessage(session);
            message.setFrom(new InternetAddress(from));
            message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
            message.setSubject("Subject");
            message.setContent("<h1>Hello</h1>", "text/html");
            Transport.send(message);
            System.out.println("Sent message successfully....");
        }
        catch (Exception ex) {
            ex.printStackTrace();
            throw new WebApplicationException(ex.getMessage());
        }
        return Response.ok().entity("Mail has been sent successfully").build();
    }
}

The SMTP_HOST enviornmental variable should hold the Fake SMTP server host. In this case, we have to link the Fake SMTP service with the REST container and give that service. Refer the below docker-compose.yml file to know how to do that.

mail-rest-docker/blob/master/docker-compose.yml


rest:
    image: mail-rest:latest
    ports:
        - 8080:8080
    environment:
       - SMTP_HOST=mail
    links:
      - mail:mail
mail:
    image: fake-smtp:latest
    volumes:
     - ./output:/output
    expose:
     - 25

Here we have mounted the local output directory to output folder. so the mail content will be available under the output folder and linked the fake-smtp service and giving that in the SMTP_HOST env variable.

Follow the below steps to run this application,

1. Clone this repository
2. Package the project by running mvn Package
3. Run ‘docker images’ and confirm that the ‘mail-rest’ docker images is available.
3. Then go into fake-smtp folder and build the image by running ‘docker build -t fake-smtp:latest . ” and confirm that the ‘fake-smtp’ docker images is available.

4. Then go to project root folder(java-mail-rest) and run “docker-compose up -d”
5. Access the REST endpoint with http://localhost:8080/api/sendEmail
6. Check the output folder and confirm that there is an eml file created which has the email content

Here is the sample file content

mail-rest-docker/blob/master/output/220717072710377.eml


        Sat, 22 Jul 2017 19:27:10 +0000 (UTC)
From: test123@gmail.com
To: test123@gmail.com
Message-ID: <840194110.01500751630345.JavaMail.root@2c7d28e1a4a2>
Subject: Subject
MIME-Version: 1.0
Content-Type: text/html; charset=us-ascii
Content-Transfer-Encoding: 7bit

<h1>Hello</h1>

Refer the code @ https://github.com/dkbalachandar/mail-rest-docker

Acceptance testing with Cucumber and Selenium(Java)

In this post, I am going to show how we can write the acceptance test script with Cucumber and Selenium.

Refer my earlier post for Ruby/Cucumber Acceptance testing with Cucumber and Capybara

My objective is to write an acceptance test which opens up the browser and goes to ‘Yelp’ site and search for a restaurant and validate the results.

Refer the below feature file.
java-cucumber-selenium-test/src/test/resources/yelp/test/yelp.feature



Feature: Search Restaurants

  Scenario: Go to yelp and search for valid restaurant
    Given a user goes to Yelp
    When Search for taco bell
    Then See the List of taco bell Restaurants and confirm results contains Lower Greenville

  Scenario: Go to yelp and search for restaurant
    Given a user goes to Yelp
    When Search for Qboba
    Then See the List of Qboba Restaurants

  Scenario: Go to yelp and search for restaurant
    Given a user goes to Yelp
    When Search for Chipotle
    Then See the List of Chipotle Restaurants

  Scenario: Go to yelp and search for invalid restaurant
    Given a user goes to Yelp
    When Search for hhahsdahsdhasd
    Then See No Results found error message

  Scenario Outline:Go to yelp and search for <searchText>
    Given a user goes to Yelp
    When Search for <searchText>
    Then See the List of  Restaurants
    Examples:
      | searchText               |
      | Scardello                |
      | Roti Grill               |
      | Mughlai Restaurant       |
      | Spice In The City Dallas |


Refer the below Junit test file
java-cucumber-selenium-test/src/test/java/yelp/test/YelpTest.java



package yelp.test;

import org.junit.runner.RunWith;
import cucumber.api.junit.Cucumber;

@RunWith(Cucumber.class)
public class YelpTest {
}

Refer the below Step definitions file.

java-cucumber-selenium-test/src/test/java/yelp/test/definitions/YelpStepDefinition.java



package yelp.test.definitions;

import cucumber.api.java.After;
import cucumber.api.java.Before;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.util.concurrent.TimeUnit;

import static org.junit.Assert.assertEquals;

public class YelpStepDefinition {

    protected WebDriver driver;

    @Before
    public void setup() {
        driver = new FirefoxDriver();
        //Loading the driver
        System.setProperty("webdriver.gecko.driver", "/usr/local/bin/geckodriver");
    }

    @Given("^a user goes to Yelp$")
    public void goToYelp() {
        //Get the Yelp home page
        driver.get("https://www.yelp.com/dallas");
    }

    @When("^Search for (.*?)$")
    public void doSearch(String searchTerm) throws InterruptedException {
        WebElement searchDescElement = driver.findElement(By.id("find_desc"));
        searchDescElement.sendKeys(searchTerm);

        WebElement submit = driver.findElement(By.id("header-search-submit"));
        submit.submit();
    }

    @Then("^See the List of (.*?) Restaurants$")
    public void verifyContents(String restaurant) {

        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        assertEquals(true, isContentAvailable(restaurant));
    }

    @Then("^See the List of (.*?) Restaurants and confirm results contains (.*?)$")
    public void verifyContentsWithLandmark(String restaurant, String landMark) {
        //Create an Explicit wait to make sure that the page is loaded and driver updates the page data.
        WebDriverWait myWait = new WebDriverWait(driver, 10);
        myWait.until(ExpectedConditions.visibilityOfElementLocated(By.id("yelp_main_body")));
        assertEquals(true, isContentAvailable(restaurant, landMark));
    }

    public boolean isContentAvailable(String... contents) {
        WebElement searchResultsElement = driver.findElement(By.id("yelp_main_body"));
        boolean result = false;
        for (String content : contents) {
            result = searchResultsElement.getText().contains(content);
        }
        return result;
    }

    @Then("^See No Results found error message")
    public void verifyContents() {
        //Create an Explicit wait to make sure that the page is loaded and driver updates the page data.
        WebDriverWait myWait = new WebDriverWait(driver, 10);
        myWait.until(ExpectedConditions.visibilityOfElementLocated(By.id("yelp_main_body")));
        assertEquals(true, driver.getPageSource().contains("No Results"));
    }

    @After
    public void closeBrowser() {
        driver.quit();
    }
}


Follow the below steps to run the test script

1. Download the repository
2. Download the ‘gecko’ driver from https://github.com/mozilla/geckodriver/releases and copy it into ‘/usr/local/bin/’
3. Do ‘mvn clean install’
4. Maven builds the test class and runs it. We can also run the test case(YelpTest.java) from any IDE as normal Junit test case.