blob: 241864aff1b2a055919fa48d64cec6c32e7d2360 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.struts2.dispatcher;
import com.mockobjects.dynamic.C;
import com.mockobjects.dynamic.Mock;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.LocalizedTextProvider;
import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.StubValueStack;
import com.opensymphony.xwork2.config.Configuration;
import com.opensymphony.xwork2.config.ConfigurationManager;
import com.opensymphony.xwork2.config.entities.InterceptorMapping;
import com.opensymphony.xwork2.config.entities.InterceptorStackConfig;
import com.opensymphony.xwork2.config.entities.PackageConfig;
import com.opensymphony.xwork2.inject.Container;
import com.opensymphony.xwork2.interceptor.Interceptor;
import com.opensymphony.xwork2.mock.MockActionInvocation;
import com.opensymphony.xwork2.mock.MockActionProxy;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.StrutsConstants;
import org.apache.struts2.StrutsInternalTestCase;
import org.apache.struts2.dispatcher.mapper.ActionMapping;
import org.apache.struts2.dispatcher.multipart.MultiPartRequestWrapper;
import org.apache.struts2.util.ObjectFactoryDestroyable;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockHttpSession;
import org.springframework.mock.web.MockServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
/**
* Test case for Dispatcher.
*/
public class DispatcherTest extends StrutsInternalTestCase {
public void testDefaultResourceBundlePropertyLoaded() {
LocalizedTextProvider localizedTextProvider = container.getInstance(LocalizedTextProvider.class);
// some i18n messages from xwork-messages.properties
assertEquals(localizedTextProvider.findDefaultText("xwork.error.action.execution", Locale.US),
"Error during Action invocation");
// some i18n messages from struts-messages.properties
assertEquals(localizedTextProvider.findDefaultText("struts.messages.error.uploading", Locale.US,
new Object[]{"some error messages"}),
"Error uploading: some error messages");
}
public void testPrepareSetEncodingProperly() {
HttpServletRequest req = new MockHttpServletRequest();
HttpServletResponse res = new MockHttpServletResponse();
Dispatcher du = initDispatcher(new HashMap<String, String>() {{
put(StrutsConstants.STRUTS_I18N_ENCODING, "utf-8");
}});
du.prepare(req, res);
assertEquals(req.getCharacterEncoding(), "utf-8");
assertEquals(res.getCharacterEncoding(), "utf-8");
}
public void testEncodingForXMLHttpRequest() {
// given
MockHttpServletRequest req = new MockHttpServletRequest();
req.addHeader("X-Requested-With", "XMLHttpRequest");
req.setCharacterEncoding("UTF-8");
HttpServletResponse res = new MockHttpServletResponse();
Dispatcher du = initDispatcher(new HashMap<String, String>() {{
put(StrutsConstants.STRUTS_I18N_ENCODING, "latin-2");
}});
// when
du.prepare(req, res);
// then
assertEquals(req.getCharacterEncoding(), "UTF-8");
assertEquals(res.getCharacterEncoding(), "UTF-8");
}
public void testSetEncodingIfDiffer() {
// given
Mock mock = new Mock(HttpServletRequest.class);
mock.expectAndReturn("getCharacterEncoding", "utf-8");
mock.expectAndReturn("getHeader", "X-Requested-With", "");
mock.expectAndReturn("getCharacterEncoding", "utf-8");
HttpServletRequest req = (HttpServletRequest) mock.proxy();
HttpServletResponse res = new MockHttpServletResponse();
Dispatcher du = initDispatcher(new HashMap<String, String>() {{
put(StrutsConstants.STRUTS_I18N_ENCODING, "utf-8");
}});
// when
du.prepare(req, res);
// then
assertEquals(req.getCharacterEncoding(), "utf-8");
assertEquals(res.getCharacterEncoding(), "utf-8");
mock.verify();
}
public void testPrepareSetEncodingPropertyWithMultipartRequest() {
MockHttpServletRequest req = new MockHttpServletRequest();
MockHttpServletResponse res = new MockHttpServletResponse();
req.setContentType("multipart/form-data");
Dispatcher du = initDispatcher(new HashMap<String, String>() {{
put(StrutsConstants.STRUTS_I18N_ENCODING, "utf-8");
}});
du.prepare(req, res);
assertEquals("utf-8", req.getCharacterEncoding());
assertEquals("utf-8", res.getCharacterEncoding());
}
public void testPrepareMultipartRequest() throws Exception {
MockHttpServletRequest req = new MockHttpServletRequest();
MockHttpServletResponse res = new MockHttpServletResponse();
req.setMethod("post");
req.setContentType("multipart/form-data; boundary=asdcvb345asd");
Dispatcher du = initDispatcher(Collections.emptyMap());
du.prepare(req, res);
HttpServletRequest wrapped = du.wrapRequest(req);
assertTrue(wrapped instanceof MultiPartRequestWrapper);
}
public void testPrepareMultipartRequestAllAllowedCharacters() throws Exception {
MockHttpServletRequest req = new MockHttpServletRequest();
MockHttpServletResponse res = new MockHttpServletResponse();
req.setMethod("post");
req.setContentType("multipart/form-data; boundary=01=23a.bC:D((e)d'z?p+o_r,e-");
Dispatcher du = initDispatcher(Collections.emptyMap());
du.prepare(req, res);
HttpServletRequest wrapped = du.wrapRequest(req);
assertTrue(wrapped instanceof MultiPartRequestWrapper);
}
public void testPrepareMultipartRequestIllegalCharacter() throws Exception {
MockHttpServletRequest req = new MockHttpServletRequest();
MockHttpServletResponse res = new MockHttpServletResponse();
req.setMethod("post");
req.setContentType("multipart/form-data; boundary=01=2;3a.bC:D((e)d'z?p+o_r,e-");
Dispatcher du = initDispatcher(Collections.emptyMap());
du.prepare(req, res);
HttpServletRequest wrapped = du.wrapRequest(req);
assertFalse(wrapped instanceof MultiPartRequestWrapper);
}
public void testDispatcherListener() {
final DispatcherListenerState state = new DispatcherListenerState();
Dispatcher.addDispatcherListener(new DispatcherListener() {
public void dispatcherDestroyed(Dispatcher du) {
state.isDestroyed = true;
}
public void dispatcherInitialized(Dispatcher du) {
state.isInitialized = true;
}
});
assertFalse(state.isDestroyed);
assertFalse(state.isInitialized);
Dispatcher du = initDispatcher(new HashMap<>());
assertTrue(state.isInitialized);
du.cleanup();
assertTrue(state.isDestroyed);
}
public void testConfigurationManager() {
Dispatcher du;
final InternalConfigurationManager configurationManager = new InternalConfigurationManager(Container.DEFAULT_NAME);
try {
du = new MockDispatcher(new MockServletContext(), new HashMap<>(), configurationManager);
du.init();
Dispatcher.setInstance(du);
assertFalse(configurationManager.destroyConfiguration);
du.cleanup();
assertTrue(configurationManager.destroyConfiguration);
} finally {
Dispatcher.setInstance(null);
}
}
public void testInitLoadsDefaultConfig() {
Dispatcher du = new Dispatcher(new MockServletContext(), new HashMap<>());
du.init();
Configuration config = du.getConfigurationManager().getConfiguration();
assertNotNull(config);
HashSet<String> expected = new HashSet<>();
expected.add("struts-default.xml");
expected.add("struts-beans.xml");
expected.add("struts-excluded-classes.xml");
expected.add("struts-plugin.xml");
expected.add("struts.xml");
assertEquals(expected, config.getLoadedFileNames());
assertTrue(config.getPackageConfigs().size() > 0);
PackageConfig packageConfig = config.getPackageConfig("struts-default");
assertTrue(packageConfig.getInterceptorConfigs().size() > 0);
assertTrue(packageConfig.getResultTypeConfigs().size() > 0);
}
public void testObjectFactoryDestroy() {
ConfigurationManager cm = new ConfigurationManager(Container.DEFAULT_NAME);
Dispatcher du = new MockDispatcher(new MockServletContext(), new HashMap<>(), cm);
Mock mockConfiguration = new Mock(Configuration.class);
cm.setConfiguration((Configuration) mockConfiguration.proxy());
Mock mockContainer = new Mock(Container.class);
final InnerDestroyableObjectFactory destroyedObjectFactory = new InnerDestroyableObjectFactory();
destroyedObjectFactory.setContainer((Container) mockContainer.proxy());
mockContainer.expectAndReturn("getInstance", C.args(C.eq(ObjectFactory.class)), destroyedObjectFactory);
mockConfiguration.expectAndReturn("getContainer", mockContainer.proxy());
mockConfiguration.expect("destroy");
mockConfiguration.matchAndReturn("getPackageConfigs", new HashMap<String, PackageConfig>());
du.init();
assertFalse(destroyedObjectFactory.destroyed);
du.cleanup();
assertTrue(destroyedObjectFactory.destroyed);
mockConfiguration.verify();
mockContainer.verify();
}
public void testInterceptorDestroy() {
Mock mockInterceptor = new Mock(Interceptor.class);
mockInterceptor.matchAndReturn("hashCode", 0);
mockInterceptor.expect("destroy");
InterceptorMapping interceptorMapping = new InterceptorMapping("test", (Interceptor) mockInterceptor.proxy());
InterceptorStackConfig isc = new InterceptorStackConfig.Builder("test").addInterceptor(interceptorMapping).build();
PackageConfig packageConfig = new PackageConfig.Builder("test").addInterceptorStackConfig(isc).build();
Map<String, PackageConfig> packageConfigs = new HashMap<>();
packageConfigs.put("test", packageConfig);
Mock mockContainer = new Mock(Container.class);
mockContainer.matchAndReturn("getInstance", C.args(C.eq(ObjectFactory.class)), new ObjectFactory());
Mock mockConfiguration = new Mock(Configuration.class);
mockConfiguration.matchAndReturn("getPackageConfigs", packageConfigs);
mockConfiguration.matchAndReturn("getContainer", mockContainer.proxy());
mockConfiguration.expect("destroy");
ConfigurationManager configurationManager = new ConfigurationManager(Container.DEFAULT_NAME);
configurationManager.setConfiguration((Configuration) mockConfiguration.proxy());
Dispatcher dispatcher = new MockDispatcher(new MockServletContext(), new HashMap<>(), configurationManager);
dispatcher.init();
dispatcher.cleanup();
mockInterceptor.verify();
mockContainer.verify();
mockConfiguration.verify();
}
public void testMultipartSupportEnabledByDefault() {
HttpServletRequest req = new MockHttpServletRequest();
HttpServletResponse res = new MockHttpServletResponse();
Dispatcher du = initDispatcher(Collections.emptyMap());
du.prepare(req, res);
assertTrue(du.isMultipartSupportEnabled(req));
}
public void testIsMultipartRequest() {
MockHttpServletRequest req = new MockHttpServletRequest();
HttpServletResponse res = new MockHttpServletResponse();
req.setMethod("POST");
Dispatcher du = initDispatcher(Collections.emptyMap());
du.prepare(req, res);
req.setContentType("multipart/form-data");
assertTrue(du.isMultipartRequest(req));
req.setContentType("multipart/form-data; boundary=---------------------------207103069210263");
assertTrue(du.isMultipartRequest(req));
req.setContentType("multipart/form-data; boundary=---------------------------207103069210263;charset=UTF-8");
assertTrue(du.isMultipartRequest(req));
req.setContentType("multipart/form-data; boundary=---------------------------207103069210263;charset=ISO-8859-1");
assertTrue(du.isMultipartRequest(req));
req.setContentType("multipart/form-data; boundary=---------------------------207103069210263;charset=Windows-1250");
assertTrue(du.isMultipartRequest(req));
req.setContentType("multipart/form-data; boundary=---------------------------207103069210263;charset=US-ASCII");
assertTrue(du.isMultipartRequest(req));
req.setContentType("multipart/form-data; boundary=---------------------------207103069210263;charset=UTF-16LE");
assertTrue(du.isMultipartRequest(req));
req.setContentType("multipart/form-data;boundary=---------------------------207103069210263;charset=UTF-16LE");
assertTrue(du.isMultipartRequest(req));
req.setContentType("multipart/form-data;boundary=---------------------------207103069210263; charset=UTF-16LE");
assertTrue(du.isMultipartRequest(req));
req.setContentType("multipart/form-data;boundary=---------------------------207103069210263 ;charset=UTF-16LE");
assertTrue(du.isMultipartRequest(req));
req.setContentType("multipart/form-data;boundary=---------------------------207103069210263 ; charset=UTF-16LE");
assertTrue(du.isMultipartRequest(req));
req.setContentType("multipart/form-data ;boundary=---------------------------207103069210263;charset=UTF-16LE");
assertTrue(du.isMultipartRequest(req));
req.setContentType("multipart/form-data ; boundary=---------------------------207103069210263;charset=UTF-16LE");
assertTrue(du.isMultipartRequest(req));
req.setContentType("Multipart/Form-Data ; boundary=---------------------------207103069210263;charset=UTF-16LE");
assertTrue(du.isMultipartRequest(req));
}
public void testServiceActionResumePreviousProxy() throws Exception {
Dispatcher du = initDispatcher(Collections.emptyMap());
MockActionInvocation mai = new MockActionInvocation();
ActionContext.getContext().withActionInvocation(mai);
MockActionProxy actionProxy = new MockActionProxy();
actionProxy.setInvocation(mai);
mai.setProxy(actionProxy);
mai.setStack(new StubValueStack());
HttpServletRequest req = new MockHttpServletRequest();
req.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, mai.getStack());
assertFalse(actionProxy.isExecutedCalled());
du.setDevMode("false");
du.setHandleException("false");
du.serviceAction(req, null, new ActionMapping());
assertTrue("should execute previous proxy", actionProxy.isExecutedCalled());
}
public void testServiceActionCreatesNewProxyIfDifferentMapping() throws Exception {
Dispatcher du = initDispatcher(Collections.emptyMap());
container.inject(du);
MockActionInvocation mai = new MockActionInvocation();
ActionContext.getContext().withActionInvocation(mai);
MockActionProxy previousActionProxy = new MockActionProxy();
previousActionProxy.setActionName("first-action");
previousActionProxy.setNamespace("namespace1");
previousActionProxy.setInvocation(mai);
mai.setProxy(previousActionProxy);
mai.setStack(new StubValueStack());
HttpServletRequest request = new MockHttpServletRequest();
request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, mai.getStack());
HttpServletResponse response = new MockHttpServletResponse();
assertFalse(previousActionProxy.isExecutedCalled());
ActionMapping newActionMapping = new ActionMapping();
newActionMapping.setName("hello");
du.serviceAction(request, response, newActionMapping);
assertFalse(previousActionProxy.isExecutedCalled());
}
/**
* Verify proper default (true) handleExceptionState for Dispatcher and that
* it properly reflects a manually configured change to false.
*/
public void testHandleException() {
Dispatcher du = initDispatcher(new HashMap<>());
assertTrue("Default Dispatcher handleException state not true ?", du.isHandleException());
Dispatcher du2 = initDispatcher(new HashMap<String, String>() {{
put(StrutsConstants.STRUTS_HANDLE_EXCEPTION, "false");
}});
assertFalse("Modified Dispatcher handleException state not false ?", du2.isHandleException());
}
/**
* Verify proper default (false) devMode for Dispatcher and that
* it properly reflects a manually configured change to true.
*/
public void testDevMode() {
Dispatcher du = initDispatcher(new HashMap<>());
assertFalse("Default Dispatcher devMode state not false ?", du.isDevMode());
Dispatcher du2 = initDispatcher(new HashMap<String, String>() {{
put(StrutsConstants.STRUTS_DEVMODE, "true");
}});
assertTrue("Modified Dispatcher devMode state not true ?", du2.isDevMode());
}
public void testGetLocale_With_DefaultLocale_FromConfiguration() {
// Given
Mock mock = new Mock(HttpServletRequest.class);
MockHttpSession mockHttpSession = new MockHttpSession();
mock.expectAndReturn("getCharacterEncoding", "utf-8"); // From Dispatcher prepare().
mock.expectAndReturn("getHeader", "X-Requested-With", ""); // From Dispatcher prepare().
mock.expectAndReturn("getParameterMap", new HashMap<String, Object>()); // From Dispatcher prepare().
mock.expectAndReturn("getSession", false, mockHttpSession); // From Dispatcher prepare().
mock.expectAndReturn("getSession", true, mockHttpSession); // From createTestContextMap().
HttpServletRequest request = (HttpServletRequest) mock.proxy();
HttpServletResponse response = new MockHttpServletResponse();
Dispatcher testDispatcher = initDispatcher(new HashMap<String, String>() {{
put(StrutsConstants.STRUTS_I18N_ENCODING, "utf-8");
// Not setting a Struts Locale here, so we should receive the default "de_DE" from the test configuration.
}});
// When
testDispatcher.prepare(request, response);
Map<String, Object> contextMap = createTestContextMap(testDispatcher, request, response);
// Then
assertEquals(Locale.GERMANY, contextMap.get(ActionContext.LOCALE)); // Expect the Dispatcher defaultLocale value "de_DE" from the test configuration.
mock.verify();
}
public void testGetLocale_With_DefaultLocale_fr_CA() {
// Given
Mock mock = new Mock(HttpServletRequest.class);
MockHttpSession mockHttpSession = new MockHttpSession();
mock.expectAndReturn("getCharacterEncoding", "utf-8"); // From Dispatcher prepare().
mock.expectAndReturn("getHeader", "X-Requested-With", ""); // From Dispatcher prepare().
mock.expectAndReturn("getParameterMap", new HashMap<String, Object>()); // From Dispatcher prepare().
mock.expectAndReturn("getSession", false, mockHttpSession); // From Dispatcher prepare().
mock.expectAndReturn("getSession", true, mockHttpSession); // From createTestContextMap().
HttpServletRequest request = (HttpServletRequest) mock.proxy();
HttpServletResponse response = new MockHttpServletResponse();
Dispatcher testDispatcher = initDispatcher(new HashMap<String, String>() {{
put(StrutsConstants.STRUTS_I18N_ENCODING, "utf-8");
put(StrutsConstants.STRUTS_LOCALE, Locale.CANADA_FRENCH.toString()); // Set the Dispatcher defaultLocale to fr_CA.
}});
// When
testDispatcher.prepare(request, response);
Map<String, Object> contextMap = createTestContextMap(testDispatcher, request, response);
// Then
assertEquals(Locale.CANADA_FRENCH, contextMap.get(ActionContext.LOCALE)); // Expect the Dispatcher defaultLocale value.
mock.verify();
}
public void testGetLocale_With_BadDefaultLocale_RequestLocale_en_UK() {
// Given
Mock mock = new Mock(HttpServletRequest.class);
MockHttpSession mockHttpSession = new MockHttpSession();
mock.expectAndReturn("getCharacterEncoding", "utf-8"); // From Dispatcher prepare().
mock.expectAndReturn("getHeader", "X-Requested-With", ""); // From Dispatcher prepare().
mock.expectAndReturn("getLocale", Locale.UK); // From Dispatcher prepare().
mock.expectAndReturn("getParameterMap", new HashMap<String, Object>()); // From Dispatcher prepare().
mock.expectAndReturn("getSession", false, mockHttpSession); // From Dispatcher prepare().
mock.expectAndReturn("getSession", true, mockHttpSession); // From createTestContextMap().
mock.expectAndReturn("getLocale", Locale.UK); // From createTestContextMap().
HttpServletRequest request = (HttpServletRequest) mock.proxy();
HttpServletResponse response = new MockHttpServletResponse();
Dispatcher testDispatcher = initDispatcher(new HashMap<String, String>() {{
put(StrutsConstants.STRUTS_I18N_ENCODING, "utf-8");
put(StrutsConstants.STRUTS_LOCALE, "This_is_not_a_valid_Locale_string"); // Set Dispatcher defaultLocale to an invalid value.
}});
// When
testDispatcher.prepare(request, response);
Map<String, Object> contextMap = createTestContextMap(testDispatcher, request, response);
// Then
assertEquals(Locale.UK, contextMap.get(ActionContext.LOCALE)); // Expect the request set value from Mock.
mock.verify();
}
public void testGetLocale_With_BadDefaultLocale_And_RuntimeException() {
// Given
Mock mock = new Mock(HttpServletRequest.class);
MockHttpSession mockHttpSession = new MockHttpSession();
mock.expectAndReturn("getCharacterEncoding", "utf-8"); // From Dispatcher prepare().
mock.expectAndReturn("getHeader", "X-Requested-With", ""); // From Dispatcher prepare().
mock.expectAndReturn("getLocale", Locale.UK); // From Dispatcher prepare().
mock.expectAndReturn("getParameterMap", new HashMap<String, Object>()); // From Dispatcher prepare().
mock.expectAndReturn("getSession", false, mockHttpSession); // From Dispatcher prepare().
mock.expectAndReturn("getSession", true, mockHttpSession); // From createTestContextMap().
mock.expectAndThrow("getLocale", new IllegalStateException("Test theoretical state preventing HTTP Request Locale access")); // From createTestContextMap().
HttpServletRequest request = (HttpServletRequest) mock.proxy();
HttpServletResponse response = new MockHttpServletResponse();
Dispatcher testDispatcher = initDispatcher(new HashMap<String, String>() {{
put(StrutsConstants.STRUTS_I18N_ENCODING, "utf-8");
put(StrutsConstants.STRUTS_LOCALE, "This_is_not_a_valid_Locale_string"); // Set the Dispatcher defaultLocale to an invalid value.
}});
// When
testDispatcher.prepare(request, response);
Map<String, Object> contextMap = createTestContextMap(testDispatcher, request, response);
// Then
assertEquals(Locale.getDefault(), contextMap.get(ActionContext.LOCALE)); // Expect the system default value, when BOTH Dispatcher default Locale AND request access fail.
mock.verify();
}
public void testGetLocale_With_NullDefaultLocale() {
// Given
Mock mock = new Mock(HttpServletRequest.class);
MockHttpSession mockHttpSession = new MockHttpSession();
mock.expectAndReturn("getCharacterEncoding", "utf-8"); // From Dispatcher prepare().
mock.expectAndReturn("getHeader", "X-Requested-With", ""); // From Dispatcher prepare().
mock.expectAndReturn("getLocale", Locale.CANADA_FRENCH); // From Dispatcher prepare().
mock.expectAndReturn("getParameterMap", new HashMap<String, Object>()); // From Dispatcher prepare().
mock.expectAndReturn("getSession", false, mockHttpSession); // From Dispatcher prepare().
mock.expectAndReturn("getSession", true, mockHttpSession); // From createTestContextMap().
mock.expectAndReturn("getLocale", Locale.CANADA_FRENCH); // From createTestContextMap().
HttpServletRequest request = (HttpServletRequest) mock.proxy();
HttpServletResponse response = new MockHttpServletResponse();
Dispatcher testDispatcher = initDispatcher(new HashMap<String, String>() {{
put(StrutsConstants.STRUTS_I18N_ENCODING, "utf-8");
// Attempting to set StrutsConstants.STRUTS_LOCALE to null here via parameters causes an NPE.
}});
testDispatcher.setDefaultLocale(null); // Force a null Struts default locale, otherwise we receive the default "de_DE" from the test configuration.
// When
testDispatcher.prepare(request, response);
Map<String, Object> contextMap = createTestContextMap(testDispatcher, request, response);
// Then
assertEquals(Locale.CANADA_FRENCH, contextMap.get(ActionContext.LOCALE)); // Expect the request set value from Mock.
mock.verify();
}
public void testGetLocale_With_NullDefaultLocale_And_RuntimeException() {
// Given
Mock mock = new Mock(HttpServletRequest.class);
MockHttpSession mockHttpSession = new MockHttpSession();
mock.expectAndReturn("getCharacterEncoding", "utf-8"); // From Dispatcher prepare().
mock.expectAndReturn("getHeader", "X-Requested-With", ""); // From Dispatcher prepare().
mock.expectAndReturn("getLocale", Locale.CANADA_FRENCH); // From Dispatcher prepare().
mock.expectAndReturn("getParameterMap", new HashMap<String, Object>()); // From Dispatcher prepare().
mock.expectAndReturn("getSession", false, mockHttpSession); // From Dispatcher prepare().
mock.expectAndReturn("getSession", true, mockHttpSession); // From createTestContextMap().
mock.expectAndThrow("getLocale", new IllegalStateException("Test some theoretical state preventing HTTP Request Locale access")); // From createTestContextMap().
HttpServletRequest request = (HttpServletRequest) mock.proxy();
HttpServletResponse response = new MockHttpServletResponse();
Dispatcher testDispatcher = initDispatcher(new HashMap<String, String>() {{
put(StrutsConstants.STRUTS_I18N_ENCODING, "utf-8");
// Attempting to set StrutsConstants.STRUTS_LOCALE to null via parameters causes an NPE.
}});
testDispatcher.setDefaultLocale(null); // Force a null Struts default locale, otherwise we receive the default "de_DE" from the test configuration.
// When
testDispatcher.prepare(request, response);
Map<String, Object> contextMap = createTestContextMap(testDispatcher, request, response);
// Then
assertEquals(Locale.getDefault(), contextMap.get(ActionContext.LOCALE)); // Expect the system default value when Mock request access fails.
mock.verify();
}
/**
* Create a test context Map from a Dispatcher instance.
* <p>
* The method directly calls getParameterMap() and getSession(true) on the HttpServletRequest.
* <p>
* The method indirectly calls getLocale(request) on the Dispatcher instance, allowing a test of that code path.
* The derived Struts Dispatcher Locale can be retrieved from the Map afterwards.
*/
protected static Map<String, Object> createTestContextMap(Dispatcher dispatcher,
HttpServletRequest request, HttpServletResponse response) {
if (dispatcher == null) {
throw new IllegalArgumentException("Cannot create a test ContextMap from a null Dispatcher");
}
if (request == null) {
throw new IllegalArgumentException("Cannot create a test ContextMap from a null HttpServletRequest");
}
if (response == null) {
throw new IllegalArgumentException("Cannot create a test ContextMap from a null HttpServletResponse");
}
return dispatcher.createContextMap(new RequestMap(request),
HttpParameters.create(request.getParameterMap()).build(),
new SessionMap(request),
new ApplicationMap(request.getSession(true).getServletContext()),
request,
response);
}
static class InternalConfigurationManager extends ConfigurationManager {
public boolean destroyConfiguration = false;
public InternalConfigurationManager(String name) {
super(name);
}
@Override
public synchronized void destroyConfiguration() {
super.destroyConfiguration();
destroyConfiguration = true;
}
}
static class DispatcherListenerState {
public boolean isInitialized = false;
public boolean isDestroyed = false;
}
public static class InnerDestroyableObjectFactory extends ObjectFactory implements ObjectFactoryDestroyable {
public boolean destroyed = false;
public InnerDestroyableObjectFactory() {
}
public void destroy() {
destroyed = true;
}
}
}