/*
* Copyright 2012 david gonzalez.
*
* 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 com.activecq.samples.slingfilters.impl;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.Resource;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;
import javax.servlet.FilterChain;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.PrintWriter;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.withSettings;
/**
* User: david
*/
@RunWith(MockitoJUnitRunner.class)
public class SampleSlingFilterTest {
// Variables required for all tests. Define one for the test and initialize and clear in setUp and treatDown
// This shows how to mockout objects using the expected subclass
// testDoFilter_withoutRedirect show hows to mock with extra interfaces
private SlingHttpServletRequest request = null;
private SlingHttpServletResponse response = null;
private FilterChain chain = null;
private Resource resource = null;
@Before
public void setUp() throws Exception {
// Create mocks for required variables
request = mock(SlingHttpServletRequest.class);
response = mock(SlingHttpServletResponse.class);
chain = mock(FilterChain.class);
resource = mock(Resource.class);
}
@After
public void tearDown() throws Exception {
// Clear variables during teardown
// Not actually necessary as they get re-initialized in setUp
request = null;
response = null;
chain = null;
resource = null;
}
@Test
public void testDoFilter_withRedirect() throws Exception {
// Mock out test-specific behaviors on input parameters
// Return mock resource when getting the Request's resource
when(request.getResource()).thenReturn(resource);
// Return test-data path when requesting mock resource's path
// This "test" path should meet the conditions to force a redirect in the Filter
when(resource.getPath()).thenReturn("/content/samples/foo");
// Instantiate the class; This creation strategy is only used in the context of the test
// and used to expose the .doFilter(..) method which we will then test
SampleSlingFilter filter = new SampleSlingFilter();
// Execute the method with the mocks we want to test
filter.doFilter(request, response, chain);
// Perform our test's assertions via mockito verify
// For the filter we do not test against any returned value, so to test, we want to verify
// that certain methods are called a certain # of times.
// For this test case, no more chain.doFilter(..) should be executed and only a redirect should occur
// Verify no chain.doFilter(..)'s were called
verify(chain, never()).doFilter(request, response);
// Verify that response.sendRedirect(..) was called
verify(response).sendRedirect(anyString());
}
@Test
public void testDoFilter_withoutRedirect() throws Exception {
// Mocks out the Request and Response inputs as ServletRequest and ServletResponse that can
// be successfully cast to a SlingHttpServletRequest and SlingHttpServletResponse
// Typically simply mocking the subclass is preferred
ServletRequest request = mock(ServletRequest.class, withSettings().extraInterfaces(SlingHttpServletRequest.class));
ServletResponse response = mock(ServletResponse.class, withSettings().extraInterfaces(SlingHttpServletResponse.class));
// Mock out the respone's PrintWriter
when(response.getWriter()).thenReturn(mock(PrintWriter.class));
// Cast the request to a SlingHttpServletRequest (possible because of the above
// mock withSettings.extraInterfaces(..)
when(((SlingHttpServletRequest)request).getResource()).thenReturn(resource);
// Mock out the resource's getPath() method response used to determine if the Filter
// should redirect or not
when(resource.getPath()).thenReturn("/content/dont/redirect");
// Instantiate the class; This creation strategy is only used in the context of the test
// and used to expose the .doFilter(..) method which we will then test
SampleSlingFilter filter = new SampleSlingFilter();
// Execute the method with the mocks we want to test
filter.doFilter(request, response, chain);
// Cast the request to a SlingHttpServletRequest (possible because of the above
// mock withSettings.extraInterfaces(..)
// This allows access to the sendRedirect(..) so we can verify it was not called
verify((SlingHttpServletResponse)response, never()).sendRedirect(anyString());
// Verify that chain.doFilter() was called
verify(chain).doFilter(request, response);
// Verify that 2 strings were written to the response
// (This filter writes HTML comments above and below the chain.doFilter(..)
verify(response.getWriter(), times(2)).write(anyString());
}
}