/**
 * Copyright (C) 2012-2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package ninja.servlet;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import ninja.ContentTypes;
import ninja.Context;
import ninja.Cookie;
import ninja.Result;
import ninja.Results;
import ninja.Route;
import ninja.bodyparser.BodyParserEngine;
import ninja.bodyparser.BodyParserEngineManager;
import ninja.session.FlashScope;
import ninja.session.Session;
import ninja.utils.NinjaConstant;
import ninja.utils.NinjaProperties;
import ninja.utils.ResultHandler;
import ninja.validation.Validation;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import com.google.common.collect.Maps;

@RunWith(MockitoJUnitRunner.class)
public class ContextImplTest {

    @Mock
    private Session sessionCookie;

    @Mock
    private FlashScope flashCookie;

    @Mock
    private BodyParserEngineManager bodyParserEngineManager;

    @Mock
    private ServletContext servletContext;

    @Mock
    private HttpServletRequest httpServletRequest;

    @Mock
    private HttpServletResponse httpServletResponse;

    @Mock
    private Route route;

    @Mock
    private ResultHandler resultHandler;

    @Mock
    private Validation validation;

    @Mock
    private BodyParserEngine bodyParserEngine;
    
    @Mock
    private NinjaProperties ninjaProperties;

    private ContextImpl context;

    @Before
    public void setUp() {
        //default setup for httpServlet request.
        //According to servlet spec the following will be returned:
        when(httpServletRequest.getContextPath()).thenReturn("");
        when(httpServletRequest.getRequestURI()).thenReturn("/");


        context = new ContextImpl(
                bodyParserEngineManager, 
                flashCookie, 
                ninjaProperties,
                resultHandler, 
                sessionCookie,
                validation);
    }

    @Test
    public void testGetRequestUri() {

        //say the httpServletRequest to return a certain value:
        when(httpServletRequest.getRequestURI()).thenReturn("/index");

        //init the context from a (mocked) servlet
        context.init(servletContext, httpServletRequest, httpServletResponse);

        //make sure this is correct
        assertEquals("/index", context.getRequestUri());
    }

    @Test
    public void testGetHostname() {

        //say the httpServletRequest to return a certain value:
        when(httpServletRequest.getHeader("host")).thenReturn("test.com");

        //init the context from a (mocked) servlet
        context.init(servletContext, httpServletRequest, httpServletResponse);

        //make sure this is correct
        assertEquals("test.com", context.getHostname());
    }

    @Test
    public void testGetRemoteAddrReturnsDefaultRemoteAddr() {

        //say the httpServletRequest to return a certain value:
        when(httpServletRequest.getRemoteAddr()).thenReturn("mockedRemoteAddr");
        when(httpServletRequest.getHeader(Context.X_FORWARD_HEADER)).thenReturn("x-forwarded-for-mockedRemoteAddr");

        //init the context from a (mocked) servlet
        context.init(servletContext, httpServletRequest, httpServletResponse);

        //make sure this is correct
        assertEquals("mockedRemoteAddr", context.getRemoteAddr());
    }
    
    @Test
    public void testGetRemoteAddrParsesXForwardedForIfSetInApplicationConf() {

        //say the httpServletRequest to return a certain value:
        when(httpServletRequest.getRemoteAddr()).thenReturn("mockedRemoteAddr");
        when(httpServletRequest.getHeader(Context.X_FORWARD_HEADER)).thenReturn("192.168.1.44");

        when(ninjaProperties.getBooleanWithDefault(Context.NINJA_PROPERTIES_X_FORWARDED_FOR, false))
                .thenReturn(Boolean.TRUE);

        //init the context from a (mocked) servlet
        context.init(servletContext, httpServletRequest, httpServletResponse);

        //make sure this is correct
        assertEquals("192.168.1.44", context.getRemoteAddr());
    }
    
    @Test
    public void testGetRemoteAddrParsesXForwardedForIfMoreThanOneHostPresent() {

        //say the httpServletRequest to return a certain value:
        when(httpServletRequest.getRemoteAddr()).thenReturn("mockedRemoteAddr");
        when(httpServletRequest.getHeader(Context.X_FORWARD_HEADER)).thenReturn("192.168.1.1, 192.168.1.2, 192.168.1.3");

        when(ninjaProperties.getBooleanWithDefault(Context.NINJA_PROPERTIES_X_FORWARDED_FOR, false))
                .thenReturn(Boolean.TRUE);

        //init the context from a (mocked) servlet
        context.init(servletContext, httpServletRequest, httpServletResponse);

        //make sure this is correct
        assertEquals("192.168.1.1", context.getRemoteAddr());
    }
    
    @Test
    public void testGetRemoteAddrUsesFallbackIfXForwardedForIsNotValidInetAddr() {

        //say the httpServletRequest to return a certain value:
        when(httpServletRequest.getRemoteAddr()).thenReturn("mockedRemoteAddr");
        when(httpServletRequest.getHeader(Context.X_FORWARD_HEADER)).thenReturn("I_AM_NOT_A_VALID_ADDRESS");

        when(ninjaProperties.getBooleanWithDefault(Context.NINJA_PROPERTIES_X_FORWARDED_FOR, false))
                .thenReturn(Boolean.TRUE);

        //init the context from a (mocked) servlet
        context.init(servletContext, httpServletRequest, httpServletResponse);

        //make sure this is correct
        assertEquals("mockedRemoteAddr", context.getRemoteAddr());
    }

    @Test
    public void testAddCookieViaResult() {
        Cookie cookie = Cookie.builder("cookie", "yum").setDomain("domain").build();
        context.init(servletContext, httpServletRequest, httpServletResponse);
        //context.addCookie(cookie);

        //generate an arbitrary result:
        Result result = Results.html();
        result.addCookie(cookie);

        //finalize the headers => the cookies must be copied over to the servletcookies
        context.finalizeHeaders(result);

        //and verify the stuff:
        ArgumentCaptor<javax.servlet.http.Cookie> cookieCaptor = ArgumentCaptor.forClass(javax.servlet.http.Cookie.class);
        verify(httpServletResponse).addCookie(cookieCaptor.capture());

        javax.servlet.http.Cookie resultCookie = cookieCaptor.getValue();
        assertThat(resultCookie.getName(), equalTo("cookie"));
        assertThat(resultCookie.getValue(), equalTo("yum"));
        assertThat(resultCookie.getPath(), equalTo("/"));
        assertThat(resultCookie.getSecure(), equalTo(false));
        assertThat(resultCookie.getMaxAge(), equalTo(-1));
    }

    @Test
    public void getCookieTest() {
        javax.servlet.http.Cookie servletCookie1 = new javax.servlet.http.Cookie("contextCookie1", "theValue1");
        javax.servlet.http.Cookie servletCookie2 = new javax.servlet.http.Cookie("contextCookie2", "theValue2");
        javax.servlet.http.Cookie [] servletCookies = {servletCookie1, servletCookie2};

        when(httpServletRequest.getCookies()).thenReturn(servletCookies);

        context.init(servletContext, httpServletRequest, httpServletResponse);

        // negative test:
        ninja.Cookie doesNotExist = context.getCookie("doesNotExist");
        assertNull(doesNotExist);

        // test  against cookie that is really there
        ninja.Cookie cookie1 = context.getCookie("contextCookie1");

        assertEquals(cookie1.getName(), "contextCookie1");
        assertEquals(cookie1.getValue(), "theValue1");

        // test 2 against cookie that is really there
        ninja.Cookie cookie2= context.getCookie("contextCookie2");

        assertEquals(cookie2.getName(), "contextCookie2");
        assertEquals(cookie2.getValue(), "theValue2");
    }


    @Test
    public void hasCookieTest() {
        javax.servlet.http.Cookie servletCookie1 = new javax.servlet.http.Cookie("contextCookie1", "theValue1");
        javax.servlet.http.Cookie servletCookie2 = new javax.servlet.http.Cookie("contextCookie2", "theValue2");
        javax.servlet.http.Cookie [] servletCookies = {servletCookie1, servletCookie2};

        when(httpServletRequest.getCookies()).thenReturn(servletCookies);

        context.init(servletContext, httpServletRequest, httpServletResponse);

        // negative test:
        assertFalse(context.hasCookie("doesNotExist"));

        // test  against cookie that is really there
        assertTrue(context.hasCookie("contextCookie1"));

        // test 2 against cookie that is really there
        assertTrue(context.hasCookie("contextCookie2"));
    }

    @Test
    public void getCookiesTest() {

        javax.servlet.http.Cookie servletCookie1 = new javax.servlet.http.Cookie("contextCookie1", "theValue");
        javax.servlet.http.Cookie servletCookie2 = new javax.servlet.http.Cookie("contextCookie2", "theValue");
        javax.servlet.http.Cookie [] servletCookiesEmpty = {};
        javax.servlet.http.Cookie [] servletCookies = {servletCookie1, servletCookie2};

        when(httpServletRequest.getCookies()).thenReturn(servletCookiesEmpty);

        context.init(servletContext, httpServletRequest, httpServletResponse);

        //test when there are no cookies.
        assertEquals(0, context.getCookies().size());

        // now return some cookies:
        when(httpServletRequest.getCookies()).thenReturn(servletCookies);


        assertEquals(2, context.getCookies().size());


    }


    @Test
    public void testGetPathParameter() {
    	//init the context
        context.init(servletContext, httpServletRequest, httpServletResponse);

        //mock a parametermap:
        Map<String, String> parameterMap = Maps.newHashMap();
        parameterMap.put("parameter", "parameter");

        //and return the parameter map when any parameter is called...
        when(route.getPathParametersEncoded(Matchers.anyString())).thenReturn(parameterMap);

        context.setRoute(route);

        //this parameter is not there and must return null
        assertEquals(null, context.getPathParameter("parameter_not_set"));

        assertEquals("parameter", context.getPathParameter("parameter"));

    }

    @Test
    public void testGetPathParameterDecodingWorks() {
        //init the context
        context.init(servletContext, httpServletRequest, httpServletResponse);

        //mock a parametermap:
        Map<String, String> parameterMap = Maps.newHashMap();
        parameterMap.put("parameter", "blue%2Fred%3Fand+green%E2%82%AC%2f");

        //and return the parameter map when any parameter is called...
        when(route.getPathParametersEncoded(Matchers.anyString())).thenReturn(parameterMap);

        context.setRoute(route);

        //that is how the above parameter looks decoded correctly:
        assertEquals("blue/red?and+green€/", context.getPathParameter("parameter"));

    }


    @Test
    public void testGetPathParameterAsInteger() {
    	//init the context
        context.init(servletContext, httpServletRequest, httpServletResponse);

        //mock a parametermap:
        Map<String, String> parameterMap = Maps.newHashMap();
        parameterMap.put("parameter", "parameter");

        //and return the parameter map when any parameter is called...
        when(route.getPathParametersEncoded(Matchers.anyString())).thenReturn(parameterMap);

        context.setRoute(route);

        //this will not work and return null
        assertEquals(null, context.getPathParameterAsInteger("parameter"));

        //now set an integer into the parametermap:
        parameterMap.put("parameter", "1");

        //this will work and return 1
        assertEquals(new Integer(1), context.getPathParameterAsInteger("parameter"));

    }

    @Test
    public void testGetParameter() {

    	//init the context
        context.init(servletContext, httpServletRequest, httpServletResponse);

        //and return the parameter map when any parameter is called...
        when(httpServletRequest.getParameter("key")).thenReturn("value");

        //this will not work and return null
        assertEquals(null, context.getParameter("key_not_there"));

        //this will return the default value:
        assertEquals("defaultValue", context.getParameter("key_not_there", "defaultValue"));

        //this will work as the value is there...
        assertEquals("value", context.getParameter("key"));

    }

    @Test
    public void testGetParameterAsInteger() {

    	//init the context
        context.init(servletContext, httpServletRequest, httpServletResponse);

        //and return the parameter map when any parameter is called...
        when(httpServletRequest.getParameter("key")).thenReturn("1");

        //this will not work and return null
        assertEquals(null, context.getParameterAsInteger("key_not_there"));

        //this will return the default value:
        assertEquals(new Integer(100), context.getParameterAsInteger("key_not_there", 100));

        //this will work as the value is there...
        assertEquals(new Integer(1), context.getParameterAsInteger("key"));

    }

    @Test
    public void testGetParameterAs() {
        //init the context
        context.init(servletContext, httpServletRequest, httpServletResponse);

        //and return the parameter map when any parameter is called...
        when(httpServletRequest.getParameter("key1")).thenReturn("100");
        when(httpServletRequest.getParameter("key2")).thenReturn("true");
        when(httpServletRequest.getParameter("key3")).thenReturn("10.1");
        when(httpServletRequest.getParameter("key4")).thenReturn("x");

        //this will not work and return null
        assertEquals(null, context.getParameterAs("key", Long.class));

        assertEquals(new Integer(100), context.getParameterAs("key1", Integer.class));
        assertEquals(new Long(100), context.getParameterAs("key1", Long.class));
        assertEquals(Boolean.TRUE, context.getParameterAs("key2", Boolean.class));
        assertEquals(new Float(10.1), context.getParameterAs("key3", Float.class));
        assertEquals(new Character('x'), context.getParameterAs("key4", Character.class));
    }

    @Test
    public void testContentTypeGetsConvertedProperlyUponFinalize() {

        //init the context
        context.init(servletContext, httpServletRequest, httpServletResponse);

        //this must be Content-Type: application/json; encoding=utf-8
        Result result = Results.json();

        context.finalizeHeaders(result);

        verify(httpServletResponse).setCharacterEncoding(result.getCharset());
        verify(httpServletResponse).setContentType(result.getContentType());
    }


    @Test
    public void testContentTypeWithNullEncodingGetsConvertedProperlyUponFinalize() {

        //init the context
        context.init(servletContext, httpServletRequest, httpServletResponse);

        //this must be Content-Type: application/json; encoding=utf-8
        Result result = Results.json();
        //force a characterset that is not there. Stupid but tests that its working.
        result.charset(null);

        context.finalizeHeaders(result);

        //make sure utf-8 is used under all circumstances:
        verify(httpServletResponse).setCharacterEncoding(NinjaConstant.UTF_8);
    }


    @Test
    public void testGetRequestPathWorksAsExpectedWithContext() {

        // we got a context
        when(httpServletRequest.getContextPath()).thenReturn("/my/funky/prefix");

        // we got a request uri
        when(httpServletRequest.getRequestURI()).thenReturn("/my/funky/prefix/myapp/is/here");


        context.init(servletContext, httpServletRequest, httpServletResponse);


        assertEquals("/myapp/is/here", context.getRequestPath());

    }

    @Test
    public void testGetRequestPathWorksAsExpectedWithOutContext() {

        // we got not context.
        // according to spec it will return an empty string
        when(httpServletRequest.getContextPath()).thenReturn("");
        when(httpServletRequest.getRequestURI()).thenReturn("/index");
        // we got a request uri
        when(httpServletRequest.getRequestURI()).thenReturn("/myapp/is/here");


        context.init(servletContext, httpServletRequest, httpServletResponse);


        assertEquals("/myapp/is/here", context.getRequestPath());

    }

    @Test
    public void testGetRequestContentType() {
        String contentType = "text/html";
        when(httpServletRequest.getContentType()).thenReturn(contentType);
        context.init(servletContext, httpServletRequest, httpServletResponse);

        assertEquals(contentType, context.getRequestContentType());

        contentType = null;
        when(httpServletRequest.getContentType()).thenReturn(contentType);
        context.init(servletContext, httpServletRequest, httpServletResponse);

        assertNull(context.getRequestContentType());

        contentType = "text/html; charset=UTF-8";
        when(httpServletRequest.getContentType()).thenReturn(contentType);
        context.init(servletContext, httpServletRequest, httpServletResponse);

        assertEquals(contentType, context.getRequestContentType());
    }

    @Test
    public void testGetAcceptContentType() {
        when(httpServletRequest.getHeader("accept")).thenReturn(null);
        context.init(servletContext, httpServletRequest, httpServletResponse);
        assertEquals(Result.TEXT_HTML, context.getAcceptContentType());

        when(httpServletRequest.getHeader("accept")).thenReturn("");
        context.init(servletContext, httpServletRequest, httpServletResponse);
        assertEquals(Result.TEXT_HTML, context.getAcceptContentType());

        when(httpServletRequest.getHeader("accept")).thenReturn("totally_unknown");
        context.init(servletContext, httpServletRequest, httpServletResponse);
        assertEquals(Result.TEXT_HTML, context.getAcceptContentType());

        when(httpServletRequest.getHeader("accept")).thenReturn("application/json");
        context.init(servletContext, httpServletRequest, httpServletResponse);
        assertEquals(Result.APPLICATON_JSON, context.getAcceptContentType());

        when(httpServletRequest.getHeader("accept")).thenReturn("text/html, application/json");
        context.init(servletContext, httpServletRequest, httpServletResponse);
        assertEquals(Result.TEXT_HTML, context.getAcceptContentType());

        when(httpServletRequest.getHeader("accept")).thenReturn("application/xhtml, application/json");
        context.init(servletContext, httpServletRequest, httpServletResponse);
        assertEquals(Result.TEXT_HTML, context.getAcceptContentType());

        when(httpServletRequest.getHeader("accept")).thenReturn("text/plain");
        context.init(servletContext, httpServletRequest, httpServletResponse);
        assertEquals(Result.TEXT_PLAIN, context.getAcceptContentType());

        when(httpServletRequest.getHeader("accept")).thenReturn("text/plain, application/json");
        context.init(servletContext, httpServletRequest, httpServletResponse);
        assertEquals(Result.APPLICATON_JSON, context.getAcceptContentType());
    }

    @Test
    public void testGetAcceptEncoding() {
        String encoding = "compress, gzip";
        when(httpServletRequest.getHeader("accept-encoding")).thenReturn(encoding);
        context.init(servletContext, httpServletRequest, httpServletResponse);

        assertEquals(encoding, context.getAcceptEncoding());

        encoding = null;
        when(httpServletRequest.getHeader("accept-encoding")).thenReturn(encoding);
        context.init(servletContext, httpServletRequest, httpServletResponse);

        assertNull(context.getAcceptEncoding());

        encoding = "gzip;q=1.0, identity; q=0.5, *;q=0";
        when(httpServletRequest.getHeader("accept-encoding")).thenReturn(encoding);
        context.init(servletContext, httpServletRequest, httpServletResponse);

        assertEquals(encoding, context.getAcceptEncoding());
    }

    @Test
    public void testGetAcceptLanguage() {
        String language = "de";
        when(httpServletRequest.getHeader("accept-language")).thenReturn(language);
        context.init(servletContext, httpServletRequest, httpServletResponse);

        assertEquals(language, context.getAcceptLanguage());

        language = null;
        when(httpServletRequest.getHeader("accept-language")).thenReturn(language);
        context.init(servletContext, httpServletRequest, httpServletResponse);

        assertNull(context.getAcceptLanguage());

        language = "da, en-gb;q=0.8, en;q=0.7";
        when(httpServletRequest.getHeader("accept-language")).thenReturn(language);
        context.init(servletContext, httpServletRequest, httpServletResponse);

        assertEquals(language, context.getAcceptLanguage());
    }

    @Test
    public void testGetAcceptCharset() {
        String charset = "UTF-8";
        when(httpServletRequest.getHeader("accept-charset")).thenReturn(charset);
        context.init(servletContext, httpServletRequest, httpServletResponse);

        assertEquals(charset, context.getAcceptCharset());

        charset = null;
        when(httpServletRequest.getHeader("accept-charset")).thenReturn(charset);
        context.init(servletContext, httpServletRequest, httpServletResponse);

        assertNull(context.getAcceptCharset());

        charset = "iso-8859-5, unicode-1-1;q=0.8";
        when(httpServletRequest.getHeader("accept-charset")).thenReturn(charset);
        context.init(servletContext, httpServletRequest, httpServletResponse);

        assertEquals(charset, context.getAcceptCharset());
    }

    /**
     * This is the default mode.
     *
     * We get a Content-Type: application/json and want to parse the incoming json.
     */
    @Test
    public void testParseBodyJsonWorks() {


        when(httpServletRequest.getContentType()).thenReturn("application/json; charset=utf-8");

        //init the context from a (mocked) servlet
        context.init(servletContext, httpServletRequest, httpServletResponse);

        when(bodyParserEngineManager.getBodyParserEngineForContentType("application/json")).thenReturn(bodyParserEngine);
        when(bodyParserEngine.invoke(context, Dummy.class)).thenReturn(new Dummy());

        Object o = context.parseBody(Dummy.class);

        verify(bodyParserEngineManager).getBodyParserEngineForContentType("application/json");
        assertTrue(o instanceof Dummy);


    }
    @Test
    public void testParseBodyPostWorks() {


        when(httpServletRequest.getContentType()).thenReturn(ContentTypes.APPLICATION_POST_FORM);

        //init the context from a (mocked) servlet
        context.init(servletContext, httpServletRequest, httpServletResponse);

        when(bodyParserEngineManager.getBodyParserEngineForContentType(ContentTypes.APPLICATION_POST_FORM)).thenReturn(bodyParserEngine);
        Dummy dummy = new Dummy();
        dummy.name = "post";
        dummy.count = 245L;
        when(bodyParserEngine.invoke(context, Dummy.class)).thenReturn(dummy);

        Dummy o = context.parseBody(Dummy.class);

        verify(bodyParserEngineManager).getBodyParserEngineForContentType(ContentTypes.APPLICATION_POST_FORM);
        assertTrue(o instanceof Dummy);
        assertTrue(o.name.equals(dummy.name));
        assertTrue(o.count.equals(dummy.count));
    }

    /**
     * Test for isJson
     */
    @Test
    public void testIsJsonWorks() {
        when(httpServletRequest.getContentType()).thenReturn(ContentTypes.APPLICATION_JSON);

        //init the context from a (mocked) servlet
        context.init(servletContext, httpServletRequest, httpServletResponse);

        assertTrue(context.isRequestJson());
    }

    /**
     * Test is isXml
     */
    @Test
    public void testIsXmlWorks() {
        when(httpServletRequest.getContentType()).thenReturn(ContentTypes.APPLICATION_XML);

        //init the context from a (mocked) servlet
        context.init(servletContext, httpServletRequest, httpServletResponse);

        assertTrue(context.isRequestXml());
    }

    /**
     * This is the default mode.
     *
     * We get a Content-Type: application/json and want to parse the incoming json.
     */
    @Test
    public void testParseBodyXmlWorks() {


        when(httpServletRequest.getContentType()).thenReturn("application/xml");

        //init the context from a (mocked) servlet
        context.init(servletContext, httpServletRequest, httpServletResponse);

        when(bodyParserEngineManager.getBodyParserEngineForContentType("application/xml")).thenReturn(bodyParserEngine);
        when(bodyParserEngine.invoke(context, Dummy.class)).thenReturn(new Dummy());

        Object o = context.parseBody(Dummy.class);

        verify(bodyParserEngineManager).getBodyParserEngineForContentType("application/xml");
        assertTrue(o instanceof Dummy);


    }

    /**
     * The request does not have the Content-Type set => we get a null response.
     */
    @Test
    public void testParseBodyWithUnkownContentTypeWorks() {

        when(httpServletRequest.getContentType()).thenReturn(null);

        //init the context from a (mocked) servlet
        context.init(servletContext, httpServletRequest, httpServletResponse);


        Object o = context.parseBody(Dummy.class);


        assertNull(o);

    }

    /**
     * We get an conetnt type that does not match any registered parsers.
     * This must also return null safely.
     */
    @Test
    public void testParseBodyWithUnknownRequestContentTypeWorks() {

        when(httpServletRequest.getContentType()).thenReturn("application/UNKNOWN");

        //init the context from a (mocked) servlet
        context.init(servletContext, httpServletRequest, httpServletResponse);

        Object o = context.parseBody(Dummy.class);

        assertNull(o);

    }


    // Dummy class used for parseBody tests.
    class Dummy {
       public String name;
       public Long count;
    }

    /**
     * Make sure the correct character encoding is set after init.
     */
    @Test
    public void testInitEnforcingOfCorrectEncoding() throws Exception {
        context.init(servletContext, httpServletRequest, httpServletResponse);

        //this proofs that the encoding has been set:
        verify(httpServletRequest).setCharacterEncoding(NinjaConstant.UTF_8);
    }

    /**
     * Make sure the correct character encoding is set before the
     * reader is returned.
     */
    @Test
    public void testGetReaderEnforcingOfCorrectEncoding() throws Exception {

        context.init(servletContext, httpServletRequest, httpServletResponse);

        context.getReader();
      //this proofs that the encoding has been set:
        verify(httpServletRequest).setCharacterEncoding(anyString());


    }

    /**
     * Make sure the correct character encoding is set before the
     * inputStream is returned.
     */
    @Test
    public void testGetInputStreamEnforcingOfCorrectEncoding() throws Exception {

        context.init(servletContext, httpServletRequest, httpServletResponse);

        context.getInputStream();
        //this proofs that the encoding has been set:
        verify(httpServletRequest).setCharacterEncoding(anyString());


    }

    /**
     * We get an conetnt type that does not match any registered parsers.
     * This must also return null safely.
     */
    @Test
    public void testGetServletContext() {

        //init the context from a (mocked) servlet
        context.init(servletContext, httpServletRequest, httpServletResponse);

        Object o = context.getServletContext();

        assertNotNull(o);
        assertEquals(servletContext, o);

    }

}
