/*** * 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.observer.download; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; import static org.mockito.Matchers.argThat; import static org.mockito.Matchers.eq; 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.InputStream; import java.lang.reflect.Method; import java.nio.file.Files; 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.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import br.com.caelum.vraptor.Result; import br.com.caelum.vraptor.controller.ControllerMethod; import br.com.caelum.vraptor.core.MethodInfo; import br.com.caelum.vraptor.events.MethodExecuted; public class DownloadObserverTest { @Rule public TemporaryFolder tmpdir = new TemporaryFolder(); private DownloadObserver downloadObserver; @Mock private MethodInfo methodInfo; @Mock private HttpServletResponse response; @Mock private ControllerMethod controllerMethod; @Mock private ServletOutputStream outputStream; @Mock private Result result; @Before public void setup() throws Exception { MockitoAnnotations.initMocks(this); when(response.getOutputStream()).thenReturn(outputStream); when(result.use(DownloadView.class)).thenReturn(new DownloadView(response)); downloadObserver = new DownloadObserver(); } @Test public void whenResultIsADownloadShouldUseIt() throws Exception { when(controllerMethod.getMethod()).thenReturn(getMethod("download")); Download download = mock(Download.class); when(methodInfo.getResult()).thenReturn(download); downloadObserver.download(new MethodExecuted(controllerMethod, methodInfo), result); verify(download).write(response); } @Test public void whenResultIsAnInputStreamShouldCreateAInputStreamDownload() throws Exception { when(controllerMethod.getMethod()).thenReturn(getMethod("asByte")); byte[] bytes = "abc".getBytes(); when(methodInfo.getResult()).thenReturn(new ByteArrayInputStream(bytes)); downloadObserver.download(new MethodExecuted(controllerMethod, methodInfo), result); verify(outputStream).write(argThat(is(arrayStartingWith(bytes))), eq(0), eq(3)); } @Test public void whenResultIsAnInputStreamShouldCreateAByteArrayDownload() throws Exception { when(controllerMethod.getMethod()).thenReturn(getMethod("asByte")); byte[] bytes = "abc".getBytes(); when(methodInfo.getResult()).thenReturn(bytes); downloadObserver.download(new MethodExecuted(controllerMethod, methodInfo), result); verify(outputStream).write(argThat(is(arrayStartingWith(bytes))), eq(0), eq(3)); } @Test public void whenResultIsAFileShouldCreateAFileDownload() throws Exception { when(controllerMethod.getMethod()).thenReturn(getMethod("file")); File tmp = tmpdir.newFile(); Files.write(tmp.toPath(), "abc".getBytes()); when(methodInfo.getResult()).thenReturn(tmp); downloadObserver.download(new MethodExecuted(controllerMethod, methodInfo), result); verify(outputStream).write(argThat(is(arrayStartingWith("abc".getBytes()))), eq(0), eq(3)); tmp.delete(); } @Test public void whenResultIsNullShouldDoNothing() throws Exception { when(controllerMethod.getMethod()).thenReturn(getMethod("download")); when(result.used()).thenReturn(true); downloadObserver.download(new MethodExecuted(controllerMethod, methodInfo), result); verifyZeroInteractions(response); } @Test public void whenResultWasUsedShouldDoNothing() throws Exception { when(controllerMethod.getMethod()).thenReturn(getMethod("download")); when(methodInfo.getResult()).thenReturn(null); downloadObserver.download(new MethodExecuted(controllerMethod, methodInfo), result); verifyZeroInteractions(response); } @Test public void shouldNotAcceptStringReturn() throws Exception { assertNull("String is not a Download", downloadObserver.resolveDownload("")); } @Test public void shouldAcceptFile() throws Exception { File file = tmpdir.newFile(); assertThat(downloadObserver.resolveDownload(file), instanceOf(FileDownload.class)); } @Test public void shouldAcceptInput() throws Exception { InputStream inputStream = mock(InputStream.class); assertThat(downloadObserver.resolveDownload(inputStream), instanceOf(InputStreamDownload.class)); } @Test public void shouldAcceptDownload() throws Exception { Download download = mock(Download.class); assertEquals(downloadObserver.resolveDownload(download), download); } @Test public void shouldAcceptByte() throws Exception { assertThat(downloadObserver.resolveDownload(new byte[]{}), instanceOf(ByteArrayDownload.class)); } private Matcher<byte[]> arrayStartingWith(final byte[] array) { return new TypeSafeMatcher<byte[]>() { @Override protected void describeMismatchSafely(byte[] item, Description mismatchDescription) { } @Override 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; } @Override public void describeTo(Description description) { description.appendText("a byte array starting with " + Arrays.toString(array)); } }; } static class FakeController { 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; } } private Method getMethod(String methodName) throws NoSuchMethodException { return FakeController.class.getMethod(methodName); } }