/* * Copyright 2013- Yan Bonnel * * 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 fr.ybonnel.simpleweb4j.handlers; import com.google.gson.Gson; import fr.ybonnel.simpleweb4j.SimpleWeb4j; import fr.ybonnel.simpleweb4j.entities.SimpleEntity; import fr.ybonnel.simpleweb4j.exception.FatalSimpleWeb4jException; import fr.ybonnel.simpleweb4j.exception.HttpErrorException; import fr.ybonnel.simpleweb4j.model.SimpleEntityManager; import org.eclipse.jetty.server.Request; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Spy; import org.mockito.runners.MockitoJUnitRunner; import javax.servlet.AsyncContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Collections; import static fr.ybonnel.simpleweb4j.SimpleWeb4j.setEntitiesClasses; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.mockito.Mockito.*; @RunWith(MockitoJUnitRunner.class) public class SimpleWeb4jUnitTest { static class Company { String name; Company(String name) { this.name = name; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Company company = (Company) o; if (name != null ? !name.equals(company.name) : company.name != null) return false; return true; } @Override public int hashCode() { return name != null ? name.hashCode() : 0; } } @Spy private SimpleWeb4jHandler handler; @Before public void setup() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { Method resetDefaultValues = SimpleWeb4j.class.getDeclaredMethod("resetDefaultValues"); resetDefaultValues.setAccessible(true); resetDefaultValues.invoke(null); setEntitiesClasses(); } @Test @SuppressWarnings("unchecked") public void testHandleAlreadyHandle() throws IOException, ServletException { Request request = makeMockedRequest(true, HttpMethod.GET, "path"); handler.handle(null, request, request, null); verify(handler, never()).processRoute(any(HttpServletRequest.class), any(HttpServletResponse.class), any(Route.class), anyString()); } @Test public void testHandleJsonContentType() throws IOException, ServletException { final Company expectedCompany = new Company("Github"); handler.addRoute(HttpMethod.GET, new Route<Void, Company>("path", null, ContentType.JSON) { @Override public Response<Company> handle(Void param, RouteParameters routeParams) throws HttpErrorException { return new Response<>(expectedCompany); } }); Request request = makeMockedRequest(false, HttpMethod.GET, "path"); HttpServletResponse response = mock(HttpServletResponse.class); PrintWriter writer = mock(PrintWriter.class); when(response.getWriter()).thenReturn(writer); handler.handle("target", request, request, response); verify(response).setStatus(200); verify(response).setContentType(ContentType.JSON.getValue()); verify(writer).print(new Gson().toJson(expectedCompany)); verify(writer).close(); } @Test public void testHandlePlainTextContentType() throws IOException, ServletException { final Company expectedCompany = new Company("Github"); handler.addRoute(HttpMethod.GET, new Route<Void, Company>("path", null, ContentType.PLAIN_TEXT) { @Override public Response<Company> handle(Void param, RouteParameters routeParams) throws HttpErrorException { return new Response<>(expectedCompany); } }); Request request = makeMockedRequest(false, HttpMethod.GET, "path"); HttpServletResponse response = mock(HttpServletResponse.class); PrintWriter writer = mock(PrintWriter.class); when(response.getWriter()).thenReturn(writer); handler.handle("target", request, request, response); verify(response).setStatus(200); verify(response).setContentType(ContentType.PLAIN_TEXT.getValue()); verify(writer).print(expectedCompany.toString()); verify(writer).close(); } private Request makeMockedRequest(boolean handled, HttpMethod httpMethod, String path) { Request request = mock(Request.class); when(request.isHandled()).thenReturn(handled); when(request.getMethod()).thenReturn(httpMethod.name()); when(request.getPathInfo()).thenReturn(path); when(request.getParameterNames()).thenReturn(Collections.<String>emptyEnumeration()); return request; } @Test public void testHttpError() throws IOException, ServletException { handler.addRoute(HttpMethod.GET, new Route<Void, Void>("path", null) { @Override public Response<Void> handle(Void param, RouteParameters routeParams) throws HttpErrorException { throw new HttpErrorException(417, "I'm a tea pot"); } }); Request request = makeMockedRequest(false, HttpMethod.GET, "path"); HttpServletResponse response = mock(HttpServletResponse.class); PrintWriter writer = mock(PrintWriter.class); when(response.getWriter()).thenReturn(writer); handler.handle("target", request, request, response); verify(response).setStatus(417); verify(response).setContentType(ContentType.JSON.getValue()); verify(writer).print("\"I\\u0027m a tea pot\""); verify(writer).close(); } @Test public void testHttpErrorWithEntities() throws IOException, ServletException { setEntitiesClasses(SimpleEntity.class); testHttpError(); assertNull(SimpleEntityManager.getCurrentSession()); } @Test public void testFatalError() throws IOException, ServletException { handler.addRoute(HttpMethod.GET, new Route<Void, Void>("path", null) { @Override public Response<Void> handle(Void param, RouteParameters routeParams) throws HttpErrorException { throw new NullPointerException(); } }); Request request = mock(Request.class); when(request.isHandled()).thenReturn(false); when(request.getMethod()).thenReturn("GET"); when(request.getPathInfo()).thenReturn("path"); HttpServletResponse response = mock(HttpServletResponse.class); PrintWriter writer = mock(PrintWriter.class); when(response.getWriter()).thenReturn(writer); handler.handle("target", request, request, response); verify(response).setStatus(500); verify(writer).close(); } @Test public void testFatalErrorWithEntities() throws IOException, ServletException { setEntitiesClasses(SimpleEntity.class); testFatalError(); assertNull(SimpleEntityManager.getCurrentSession()); } @Test public void testLimitOfFindRoute() { SimpleWeb4jHandler simpleWeb4jHandler = new SimpleWeb4jHandler(); assertNull(simpleWeb4jHandler.findRoute("GET", "/test")); simpleWeb4jHandler.addRoute(HttpMethod.POST, new Route<Void, Void>("/test", Void.class) { @Override public Response<Void> handle(Void param, RouteParameters routeParams) throws HttpErrorException { return null; } }); assertNull(simpleWeb4jHandler.findRoute("GET", "/test")); assertNull(simpleWeb4jHandler.findRoute("POST", "/tutu")); assertNotNull(simpleWeb4jHandler.findRoute("POST", "/test")); } @Test public void testLimitOfHandle() throws IOException { Request request = mock(Request.class); when(request.isHandled()).thenReturn(false); when(request.getMethod()).thenReturn("POST"); when(request.getPathInfo()).thenReturn("path"); HttpServletResponse response = mock(HttpServletResponse.class); PrintWriter writer = mock(PrintWriter.class); when(response.getWriter()).thenReturn(writer); handler.handle("target", request, request, response); verify(response, times(0)).setStatus(500); verify(writer, times(0)).close(); } @Test( expected = FatalSimpleWeb4jException.class) public void testLimitOfWriteHttpResponseForEventSource() throws IOException { Request request = mock(Request.class); HttpServletResponse response = mock(HttpServletResponse.class); AsyncContext asyncContext = mock(AsyncContext.class); when(request.startAsync()).thenReturn(asyncContext); handler.writeHttpResponseForEventSource(request, response, ContentType.PLAIN_TEXT, new Response<String>("string"){ @Override protected boolean isStream() { return true; } }); } }