All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.wadpam.open.AbstractRestTempleIntegrationTest Maven / Gradle / Ivy

package com.wadpam.open;

import com.wadpam.open.json.JBaseObject;
import com.wadpam.open.json.JCursorPage;
import org.apache.commons.codec.binary.Base64;
import org.junit.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RequestCallback;
import org.springframework.web.client.ResponseExtractor;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.MalformedURLException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import static org.junit.Assert.*;


/**
 * Base class for GAE, Spring, RestTemplate integration tests.
 * Contains convenience methods and help classes.
 * @author mattiaslevin
 */
public abstract class AbstractRestTempleIntegrationTest {
    private static final Logger LOG = LoggerFactory.getLogger(AbstractRestTempleIntegrationTest.class);


    // Spring rest template
    protected RestTemplate restTemplate;

    protected final String BASE_URL = getBaseUrl();

    // All sub classes must implement this method
    protected abstract String getBaseUrl();
    // TODO: If using relative paths, add the base url


    // Basic authentication
    protected String getUserName() {
        return null;
    }

    protected String getPassword() {
        return null;
    }


    @Before
    public void setUp() {
        restTemplate = new RestTemplate(new SimpleAuthClientHttpRequestFactory());

        // Configure an error handler that does not throw exceptions
        // All http codes are handled and tested using asserts
        restTemplate.setErrorHandler(new DoNothingResponseErrorHandler());
    }


    // Custom http request factory that set basic authentication if user and password is set
    protected class SimpleAuthClientHttpRequestFactory extends SimpleClientHttpRequestFactory {
        private final String BASIC_AUTH_PREFIX = "Basic ";
        private final Base64 B64 = new Base64();

        @Override
        public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {
            ClientHttpRequest httpRequest = super.createRequest(uri, httpMethod);

            if (null != getUserName() && null != getPassword()) {
                // Set basic authentication
                HttpHeaders headers = httpRequest.getHeaders();
                headers.set("Authorization", encode(getUserName(), getPassword()));
            }

            return httpRequest;
        }

        // Build basic authentication string
        private String encode(String username, String password) {
            final String decoded = String.format("%s:%s", username, password);
            return BASIC_AUTH_PREFIX + B64.encodeAsString(decoded.getBytes());
        }
    }


    // A error handler for Spring RestTemplate that ignores all http error codes.
    protected class DoNothingResponseErrorHandler extends DefaultResponseErrorHandler {
        @Override
        protected boolean hasError(HttpStatus statusCode) {
            return false;
        }
    }


    // Check that the response is a redirect (assert if not).
    // Extract the headers from from the response.
    protected class RedirectResponseExtractor implements ResponseExtractor {
        @Override
        public URI extractData(ClientHttpResponse clientHttpResponse) throws IOException {

            // Check that it is a redirect
            assertTrue("Redirect", clientHttpResponse.getStatusCode() == HttpStatus.FOUND);

            return clientHttpResponse.getHeaders().getLocation();
        }
    }

    // Extract the status code from the response
    protected class StatusCodeResponseExtractor implements ResponseExtractor {
        @Override
        public HttpStatus extractData(ClientHttpResponse clientHttpResponse) throws IOException {

            return clientHttpResponse.getStatusCode();
        }
    }

    // This class writes a map to the request body in a RestTemplate execute method.
    // The reason fro this class is that if you use the provided RestTemplate methods it will
    // not write parameters with the same name more then once.
    protected class RequestCallBackBodyWriter implements RequestCallback {

        MultiValueMap map;

        protected RequestCallBackBodyWriter(MultiValueMap map) {
            this.map = map;
        }

        @Override
        public void doWithRequest(ClientHttpRequest clientHttpRequest) throws IOException {
            StringBuilder builder = new StringBuilder();

            for (Map.Entry> entry : map.entrySet()) {
                for (Object value : entry.getValue())
                    builder.append(entry.getKey()).append("=").append(value).append("&");
            }
            LOG.debug("Write POST body:{}", builder);

            PrintWriter out = new PrintWriter(clientHttpRequest.getBody());
            out.write(builder.toString()); // TODO add url encoding
            out.flush();
            out.close();
        }
    }

    // Prepend the base url if not provided
    protected String buildUrl(String url) {
        String expandedUrl = url;
        if (!url.startsWith(getBaseUrl())) {
            if (getBaseUrl().endsWith("/") || url.startsWith("/")) {
                expandedUrl = getBaseUrl() + url;
            } else {
                expandedUrl = getBaseUrl() + "/" + url;
            }
        }
        return expandedUrl;
    }

    // Make a post and follow the redirect
    protected  ResponseEntity postAndFollowRedirect(
            String url, MultiValueMap map, Class clazz)
            throws MalformedURLException {

        URI redirectUrl = restTemplate.execute(buildUrl(url), HttpMethod.POST,
                new RequestCallBackBodyWriter(map),
                new RedirectResponseExtractor());
        assertNotNull("Redirect URL", redirectUrl);

        ResponseEntity entity = restTemplate.getForEntity(redirectUrl, clazz);
        assertEquals("Http response 200", HttpStatus.OK, entity.getStatusCode());

        return entity;
    }

    // Make a delete and follow the redirect
    protected   ResponseEntity deleteAndFollowRedirect(
            String url, MultiValueMap map, Class clazz)
            throws MalformedURLException {

        URI redirectUrl = restTemplate.execute(buildUrl(url), HttpMethod.DELETE,
                null,
                new RedirectResponseExtractor());
        assertNotNull("Redirect URL", redirectUrl);

        ResponseEntity entity = restTemplate.getForEntity(redirectUrl, clazz);
        assertEquals("Http response 200", HttpStatus.OK, entity.getStatusCode());

        return entity;
    }

    // Get the http status code of the resource
    protected HttpStatus getResourceStatusCode(URI url) {
        HttpStatus statusCode = restTemplate.execute(url,
                HttpMethod.GET,
                null, // No need to modify the request before sending
                new StatusCodeResponseExtractor());

        return statusCode;
    }

    // Get the http status code of the resource
    protected HttpStatus getResourceStatusCode(String url, Object... urlVariables) {
        HttpStatus statusCode = restTemplate.execute(buildUrl(url),
                HttpMethod.GET,
                null, // No need to modify the request before sending
                new StatusCodeResponseExtractor(),
                urlVariables);

        return statusCode;
    }


    // Check if a resource exist on the given url
    protected boolean doesResourceExist(String url, Object... urlVariables) {
        return getResourceStatusCode(url, urlVariables) == HttpStatus.OK;
    }


    // Delete a resource at the given url
    protected boolean deleteResource(String url, Object ... urlVariables) {
        HttpStatus statusCode = restTemplate.execute(buildUrl(url),
                HttpMethod.DELETE,
                null, // No need to modify the request before sending
                new StatusCodeResponseExtractor(),
                urlVariables);
        assertEquals("Http response 200", HttpStatus.OK, statusCode);

        return true;
    }

    // Delete a resource at the given url and return the JSON response
    protected  ResponseEntity deleteResource(String url, Class clazz, Object ... urlVariables) {
        ResponseEntity response = restTemplate.exchange(buildUrl(url),
                HttpMethod.DELETE,
                null,
                clazz,
                urlVariables);
        assertEquals("Http response 200", HttpStatus.OK, response.getStatusCode());

        return response;
    }

    // Delete a resource and verify that it was deleted
    protected boolean deleteResourceAndCheck(String url, Object... urlVariables) {
        deleteResource(url, urlVariables);
        assertFalse("Resource deleted", doesResourceExist(url, urlVariables));

        return true;
    }

    // Count the number of entities at the resource
    protected int countResources(String url, Object... urlVariables) {
        ResponseEntity entity =
                restTemplate.getForEntity(buildUrl(url), Collection.class, urlVariables);
        assertEquals("Http response 200", HttpStatus.OK, entity.getStatusCode());

        return entity.getBody().size();
    }

    // Count the number of entities at the result page
    protected  int countResourcesInPage(String url,  Class clazz, Object... urlVariables) {
        ParameterizedTypeReference> jCursorPage =
                new ParameterizedTypeReference>() {};

        ResponseEntity> entity = restTemplate.exchange(buildUrl(url),
                HttpMethod.GET,
                null,
                jCursorPage,
                urlVariables);
        assertEquals("Http response 200", HttpStatus.OK, entity.getStatusCode());

        return entity.getBody().getItems().size();
    }

    // Get resources in a collection
    protected  List getResourceCollection(String url,  Class clazz, Object... urlVariables) {
        ParameterizedTypeReference> list =
                new ParameterizedTypeReference>() {};

        ResponseEntity> entity = restTemplate.exchange(buildUrl(url),
                HttpMethod.GET,
                null,
                list,
                urlVariables);
        assertEquals("Http response 200", HttpStatus.OK, entity.getStatusCode());

        return entity.getBody();
    }


    // TODO Create builder

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy