/*** * Copyright (c) 2009 Caelum - www.caelum.com.br/opensource * All rights reserved. * * 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 br.com.caelum.vraptor.interceptor; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.Matchers.any; import static org.mockito.Matchers.argThat; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.lang.reflect.Method; import java.util.Arrays; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import org.hamcrest.Description; import org.hamcrest.Matcher; import org.hamcrest.TypeSafeMatcher; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import br.com.caelum.vraptor.InterceptionException; import br.com.caelum.vraptor.Result; import br.com.caelum.vraptor.core.InterceptorStack; import br.com.caelum.vraptor.core.MethodInfo; import br.com.caelum.vraptor.interceptor.download.Download; import br.com.caelum.vraptor.interceptor.download.DownloadInterceptor; import br.com.caelum.vraptor.resource.DefaultResourceMethod; import br.com.caelum.vraptor.resource.ResourceMethod; public class DownloadInterceptorTest { private DownloadInterceptor interceptor; @Mock private MethodInfo info; @Mock private HttpServletResponse response; @Mock private ResourceMethod resourceMethod; @Mock private InterceptorStack stack; @Mock private ServletOutputStream outputStream; @Mock private Result result; @Before public void setup() throws Exception { MockitoAnnotations.initMocks(this); when(response.getOutputStream()).thenReturn(outputStream); interceptor = new DownloadInterceptor(response, info, result); } @Test public void whenResultIsADownloadShouldUseIt() throws Exception { Download download = mock(Download.class); when(info.getResult()).thenReturn(download); interceptor.intercept(stack, resourceMethod, null); verify(download).write(response); } @Test public void whenResultIsAnInputStreamShouldCreateAInputStreamDownload() throws Exception { byte[] bytes = "abc".getBytes(); when(info.getResult()).thenReturn(new ByteArrayInputStream(bytes)); interceptor.intercept(stack, resourceMethod, null); verify(outputStream).write(argThat(is(arrayStartingWith(bytes))), eq(0), eq(3)); } @Test public void whenResultIsAnInputStreamShouldCreateAByteArrayDownload() throws Exception { byte[] bytes = "abc".getBytes(); when(info.getResult()).thenReturn(bytes); interceptor.intercept(stack, resourceMethod, null); verify(outputStream).write(argThat(is(arrayStartingWith(bytes))), eq(0), eq(3)); } @Test public void whenResultIsAFileShouldCreateAFileDownload() throws Exception { File tmp = File.createTempFile("test", "test"); new PrintWriter(tmp).append("abc").close(); when(info.getResult()).thenReturn(tmp); interceptor.intercept(stack, resourceMethod, null); verify(outputStream).write(argThat(is(arrayStartingWith("abc".getBytes()))), eq(0), eq(3)); } @Test public void whenResultIsNullAndResultWasUsedShouldDoNothing() throws Exception { when(info.getResult()).thenReturn(null); when(result.used()).thenReturn(true); interceptor.intercept(stack, resourceMethod, null); verify(stack).next(resourceMethod, null); verifyZeroInteractions(response); } @Test public void whenResultIsNullAndResultWasNotUsedShouldThrowNPE() throws Exception { when(info.getResult()).thenReturn(null); when(result.used()).thenReturn(false); try { interceptor.intercept(stack, resourceMethod, null); fail("expected NullPointerException"); } catch (NullPointerException e) { verifyZeroInteractions(response); } } @Test public void shouldThrowInterceptionExceptionIfIOExceptionOccurs() throws Exception { Download download = mock(Download.class); when(info.getResult()).thenReturn(download); when(result.used()).thenReturn(false); doThrow(new IOException()).when(download).write(any(HttpServletResponse.class)); try { interceptor.intercept(stack, resourceMethod, null); fail("expected InterceptionException"); } catch (InterceptionException e) { } } @Test public void shouldNotAcceptStringReturn() throws Exception { Method method = FakeResource.class.getMethod("string"); assertThat(interceptor, not(accepts(method))); } @Test public void shouldAcceptFile() throws Exception { Method method = FakeResource.class.getMethod("file"); assertThat(interceptor, accepts(method)); } @Test public void shouldAcceptInput() throws Exception { Method method = FakeResource.class.getMethod("input"); assertThat(interceptor, accepts(method)); } @Test public void shouldAcceptDownload() throws Exception { Method method = FakeResource.class.getMethod("download"); assertThat(interceptor, accepts(method)); } @Test public void shouldAcceptByte() throws Exception { Method method = FakeResource.class.getMethod("asByte"); assertThat(interceptor, accepts(method)); } private Matcher<Interceptor> accepts(final Method method) { return new TypeSafeMatcher<Interceptor>() { public void describeTo(Description description) { description.appendText("the method ").appendValue(method); } protected boolean matchesSafely(Interceptor item) { ResourceMethod m = DefaultResourceMethod.instanceFor(method.getDeclaringClass(), method); return interceptor.accepts(m); } protected void describeMismatchSafely(Interceptor item, Description mismatchDescription) { } }; } private Matcher<byte[]> arrayStartingWith(final byte[] array) { return new TypeSafeMatcher<byte[]>() { protected void describeMismatchSafely(byte[] item, Description mismatchDescription) { } protected boolean matchesSafely(byte[] item) { if (item.length < array.length) { return false; } for (int i = 0; i < array.length; i++) { if (array[i] != item[i]) { return false; } } return true; } public void describeTo(Description description) { description.appendText("a byte array starting with " + Arrays.toString(array)); } }; } static class FakeResource { public String string() { return null; } public File file() { return null; } public InputStream input() { return null; } public Download download() { return null; } public byte[] asByte() { return null; } } }