001: // StrutsTestCase - a JUnit extension for testing Struts actions
002: // within the context of the ActionServlet.
003: // Copyright (C) 2002 Deryl Seale
004: //
005: // This library is free software; you can redistribute it and/or
006: // modify it under the terms of the Apache Software License as
007: // published by the Apache Software Foundation; either version 1.1
008: // of the License, or (at your option) any later version.
009: //
010: // This library is distributed in the hope that it will be useful,
011: // but WITHOUT ANY WARRANTY; without even the implied warranty of
012: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013: // Apache Software Foundation Licens for more details.
014: //
015: // You may view the full text here: http://www.apache.org/LICENSE.txt
016:
017: package servletunit.struts;
018:
019: import junit.framework.AssertionFailedError;
020: import junit.framework.TestCase;
021: import org.apache.commons.digester.Digester;
022: import org.apache.commons.logging.Log;
023: import org.apache.commons.logging.LogFactory;
024: import org.apache.struts.Globals;
025: import org.apache.struts.action.ActionForm;
026: import org.apache.struts.action.ActionServlet;
027: import servletunit.HttpServletRequestSimulator;
028: import servletunit.HttpServletResponseSimulator;
029: import servletunit.ServletConfigSimulator;
030: import servletunit.ServletContextSimulator;
031:
032: import javax.servlet.http.*;
033: import java.io.File;
034: import java.io.InputStream;
035: import java.net.URL;
036:
037: /**
038: * MockStrutsTestCase is an extension of the base JUnit testcase that
039: * provides additional methods to aid in testing Struts Action
040: * objects. It uses a mock object approach to simulate a servlet
041: * container, and tests the execution of Action objects as they
042: * are actually run through the Struts ActionServlet. MockStrutsTestCase
043: * provides methods that set up the request path, request parameters
044: * for ActionForm subclasses, as well as methods that can verify
045: * that the correct ActionForward was used and that the proper
046: * ActionError messages were supplied.
047: *
048: *<br><br>
049: *<b>NOTE:</b> By default, the Struts ActionServlet will look for the
050: * file <code>WEB-INF/struts-config.xml</code>, so you must place
051: * the directory that <i>contains</i> WEB-INF in your CLASSPATH. If
052: * you would like to use an alternate configuration file, please see
053: * the setConfigFile() method for details on how this file is located.
054: */
055: public class MockStrutsTestCase extends TestCase {
056:
057: protected ActionServlet actionServlet;
058: protected HttpServletRequestSimulator request;
059: protected HttpServletResponseSimulator response;
060: protected HttpServletRequestWrapper requestWrapper;
061: protected HttpServletResponseWrapper responseWrapper;
062: protected ServletContextSimulator context;
063: protected ServletConfigSimulator config;
064: protected String actionPath;
065: protected boolean isInitialized = false;
066: protected boolean actionServletIsInitialized = false;
067: protected boolean requestPathSet = false;
068:
069: /**
070: * The set of public identifiers, and corresponding resource names, for
071: * the versions of the configuration file DTDs that we know about. There
072: * <strong>MUST</strong> be an even number of Strings in this list!
073: */
074: protected String registrations[] = {
075: "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN",
076: "/org/apache/struts/resources/web-app_2_2.dtd",
077: "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN",
078: "/org/apache/struts/resources/web-app_2_3.dtd" };
079:
080: protected static Log logger = LogFactory
081: .getLog(MockStrutsTestCase.class);
082:
083: /**
084: * Default constructor.
085: */
086: public MockStrutsTestCase() {
087: super ();
088: }
089:
090: /**
091: * Constructor that takes test name parameter, for backwards compatibility with older versions on JUnit.
092: */
093: public MockStrutsTestCase(String testName) {
094: super (testName);
095: }
096:
097: /**
098: * A check that every method should run to ensure that the
099: * base class setUp method has been called.
100: */
101: private void init() {
102: if (!isInitialized)
103: throw new AssertionFailedError(
104: "You are overriding the setUp() method without calling super.setUp(). You must call the superclass setUp() method in your TestCase subclass to ensure proper initialization.");
105: }
106:
107: /**
108: * Sets up the test fixture for this test. This method creates
109: * an instance of the ActionServlet, initializes it to validate
110: * forms and turn off debugging, and creates a mock HttpServletRequest
111: * and HttpServletResponse object to use in this test.
112: */
113: protected void setUp() throws Exception {
114: if (logger.isDebugEnabled())
115: logger.debug("Entering");
116: if (actionServlet == null)
117: actionServlet = new ActionServlet();
118: config = new ServletConfigSimulator();
119: request = new HttpServletRequestSimulator(config
120: .getServletContext());
121: response = new HttpServletResponseSimulator();
122: context = (ServletContextSimulator) config.getServletContext();
123: requestWrapper = null;
124: responseWrapper = null;
125: isInitialized = true;
126: if (logger.isDebugEnabled())
127: logger.debug("Exiting");
128: }
129:
130: protected void tearDown() throws Exception {
131: ActionServlet servlet = getActionServlet();
132: servlet.destroy();
133: setActionServlet(servlet);
134: }
135:
136: /**
137: * Returns an HttpServletRequest object that can be used in
138: * this test.
139: */
140: public HttpServletRequest getRequest() {
141: if (logger.isDebugEnabled())
142: logger.debug("Entering");
143: init();
144: if (logger.isDebugEnabled())
145: logger.debug("Exiting");
146: return this .request;
147: }
148:
149: /**
150: * Returns a HttpServletRequestWrapper object that can be used
151: * in this test. Note that if {@link #setRequestWrapper} has not been
152: * called, this method will return an instance of
153: * javax.servlet.http.HttpServletRequestWrapper.
154: */
155: public HttpServletRequestWrapper getRequestWrapper() {
156: if (logger.isDebugEnabled())
157: logger.debug("Entering");
158: init();
159: if (requestWrapper == null) {
160: if (logger.isDebugEnabled())
161: logger.debug("Exiting");
162: return new HttpServletRequestWrapper(this .request);
163: } else {
164: if (logger.isDebugEnabled()) {
165: logger.debug("wrapper class is '"
166: + requestWrapper.getClass() + "'");
167: }
168: if (logger.isDebugEnabled())
169: logger.debug("Exiting");
170: return requestWrapper;
171: }
172: }
173:
174: /**
175: * Set this TestCase to use a given HttpServletRequestWrapper
176: * class when calling Action.execute(). Note that if this
177: * method is not called, then the normal HttpServletRequest
178: * object is used.
179: *
180: * @param wrapper an HttpServletRequestWrapper object to be
181: * used when calling Action.execute().
182: */
183: public void setRequestWrapper(HttpServletRequestWrapper wrapper) {
184: if (logger.isDebugEnabled())
185: logger.debug("Entering - wrapper = " + wrapper);
186: init();
187: if (wrapper == null)
188: throw new IllegalArgumentException(
189: "wrapper class cannot be null!");
190: else {
191: if (wrapper.getRequest() == null)
192: wrapper.setRequest(this .request);
193: this .requestWrapper = wrapper;
194: }
195: if (logger.isDebugEnabled())
196: logger.debug("Exiting");
197: }
198:
199: /**
200: * Clears all request parameters previously set.
201: */
202: public void clearRequestParameters() {
203: if (logger.isTraceEnabled())
204: logger.trace("Entering");
205: this .request.getParameterMap().clear();
206:
207: // also, clear out the redirect header if it's there.
208: response.removeHeader("Location");
209: if (logger.isTraceEnabled())
210: logger.trace("Exiting");
211: }
212:
213: /**
214: * Returns an HttpServletResponse object that can be used in
215: * this test.
216: */
217: public HttpServletResponse getResponse() {
218: if (logger.isDebugEnabled())
219: logger.debug("Entering");
220: init();
221: if (logger.isDebugEnabled())
222: logger.debug("Exiting");
223: return this .response;
224: }
225:
226: /**
227: * Returns an HttpServletResponseWrapper object that can be used in
228: * this test. Note that if {@link #setResponseWrapper} has not been
229: * called, this method will return an instance of
230: * javax.servlet.http.HttpServletResponseWrapper.
231: */
232: public HttpServletResponseWrapper getResponseWrapper() {
233: if (logger.isDebugEnabled())
234: logger.debug("Entering");
235: init();
236: if (responseWrapper == null) {
237: if (logger.isDebugEnabled())
238: logger.debug("Exiting");
239: return new HttpServletResponseWrapper(this .response);
240: } else {
241: if (logger.isDebugEnabled()) {
242: logger.debug("wrapper class is '"
243: + responseWrapper.getClass() + "'");
244: }
245: if (logger.isDebugEnabled())
246: logger.debug("Exiting");
247: return responseWrapper;
248: }
249: }
250:
251: /**
252: * Set this TestCase to use a given HttpServletResponseWrapper
253: * class when calling Action.execute(). Note that if this
254: * method is not called, then the normal HttpServletResponse
255: * object is used.
256: *
257: * @param wrapper an HttpServletResponseWrapper object to be
258: * used when calling Action.execute().
259: */
260: public void setResponseWrapper(HttpServletResponseWrapper wrapper) {
261: if (logger.isDebugEnabled())
262: logger.debug("Entering - wrapper = " + wrapper);
263: init();
264: if (wrapper == null)
265: throw new IllegalArgumentException(
266: "wrapper class cannot be null!");
267: else {
268: if (wrapper.getResponse() == null)
269: wrapper.setResponse(this .response);
270: this .responseWrapper = wrapper;
271: }
272: if (logger.isDebugEnabled())
273: logger.debug("Exiting");
274: }
275:
276: /**
277: * Returns the mock HttpServletRequest object used in this test. This allows
278: * access to methods for setting up test preconditions that are otherwise
279: * unavailable through the normal Servlet API.
280: */
281: public HttpServletRequestSimulator getMockRequest() {
282: if (logger.isTraceEnabled())
283: logger.trace("Entering");
284: init();
285: if (logger.isTraceEnabled())
286: logger.trace("Exiting");
287: return this .request;
288: }
289:
290: /**
291: * Returns the mock HttpServletResponse object used in this test. This allows
292: * access to methods for setting up test preconditions that are otherwise
293: * unavailable through the normal Servlet API.
294: */
295: public HttpServletResponseSimulator getMockResponse() {
296: if (logger.isTraceEnabled())
297: logger.trace("Entering");
298: init();
299: if (logger.isTraceEnabled())
300: logger.trace("Exiting");
301: return this .response;
302: }
303:
304: /**
305: * Returns an HttpSession object that can be used in this
306: * test.
307: */
308: public HttpSession getSession() {
309: if (logger.isDebugEnabled())
310: logger.debug("Entering");
311: init();
312: if (logger.isDebugEnabled())
313: logger.debug("Exiting");
314: return this .request.getSession(true);
315: }
316:
317: /**
318: * Returns the ActionServlet controller used in this
319: * test.
320: *
321: */
322: public ActionServlet getActionServlet() {
323: if (logger.isDebugEnabled())
324: logger.debug("Entering");
325: init();
326: try {
327: if (!actionServletIsInitialized) {
328: if (logger.isDebugEnabled()) {
329: logger.debug("intializing actionServlet");
330: }
331: this .actionServlet.init(config);
332: actionServletIsInitialized = true;
333: }
334: } catch (Exception e) {
335: logger.error("Error initializing action servlet", e);
336: if (e.getMessage().equals("java.lang.NullPointerException")) {
337: String message = "Error initializing action servlet: Unable to find /WEB-INF/web.xml. "
338: + "TestCase is running from "
339: + System.getProperty("user.dir")
340: + " directory. " + "Context directory ";
341: if (this .context.getContextDirectory() == null) {
342: message += "has not been set. Try calling setContextDirectory() with a relative or absolute path";
343: } else {
344: message = message
345: + "is "
346: + this .context.getContextDirectory()
347: .getAbsolutePath();
348: }
349: message = message
350: + ". /WEB-INF/web.xml must be found under the context directory, "
351: + "the directory the test case is running from, or in the classpath.";
352: fail(message);
353: } else {
354: throw new AssertionFailedError(e.getMessage());
355: }
356: }
357: if (logger.isDebugEnabled())
358: logger.debug("Exiting");
359: return actionServlet;
360: }
361:
362: /**
363: * Sets the ActionServlet to be used in this test execution. This
364: * method should only be used if you plan to use a customized
365: * version different from that provided in the Struts distribution.
366: */
367: public void setActionServlet(ActionServlet servlet) {
368: if (logger.isDebugEnabled())
369: logger.debug("Entering - servlet = " + servlet);
370: init();
371: if (servlet == null)
372: throw new AssertionFailedError(
373: "Cannot set ActionServlet to null");
374: this .actionServlet = servlet;
375: if (logger.isDebugEnabled())
376: logger.debug("Exiting");
377: actionServletIsInitialized = false;
378: }
379:
380: /**
381: * Executes the Action instance to be tested. This method
382: * calls the ActionServlet.doPost() method to execute the
383: * Action instance to be tested, passing along any parameters
384: * set in the HttpServletRequest object. It stores any results
385: * for further validation.
386: *
387: * @exception AssertionFailedError if there are any execution
388: * errors while calling Action.execute()
389: *
390: */
391: public void actionPerform() {
392: if (logger.isDebugEnabled())
393: logger.debug("Entering");
394: if (!this .requestPathSet) {
395: throw new IllegalStateException(
396: "You must call setRequestPathInfo() prior to calling actionPerform().");
397: }
398: init();
399: HttpServletRequest request = this .request;
400: HttpServletResponse response = this .response;
401: if (this .requestWrapper != null)
402: request = this .requestWrapper;
403: if (this .responseWrapper != null)
404: response = this .responseWrapper;
405: try {
406: this .getActionServlet().doPost(request, response);
407: } catch (NullPointerException npe) {
408: String message = "A NullPointerException was thrown. This may indicate an error in your ActionForm, or "
409: + "it may indicate that the Struts ActionServlet was unable to find struts config file. "
410: + "TestCase is running from "
411: + System.getProperty("user.dir")
412: + " directory. "
413: + "Context directory ";
414: if (this .context.getContextDirectory() == null) {
415: message += "has not been set. Try calling setContextDirectory() with a relative or absolute path";
416: } else {
417: message = message
418: + "is "
419: + this .context.getContextDirectory()
420: .getAbsolutePath();
421: }
422: message = message
423: + ". struts config file must be found under the context directory, "
424: + "the directory the test case is running from, or in the classpath.";
425: throw new ExceptionDuringTestError(message, npe);
426: } catch (Exception e) {
427: throw new ExceptionDuringTestError(
428: "An uncaught exception was thrown during actionExecute()",
429: e);
430: }
431: if (logger.isDebugEnabled())
432: logger.debug("Exiting");
433: }
434:
435: /**
436: * Adds an HttpServletRequest parameter to be used in setting up the
437: * ActionForm instance to be used in this test. Each parameter added
438: * should correspond to an attribute in the ActionForm instance used
439: * by the Action instance being tested.
440: */
441: public void addRequestParameter(String parameterName,
442: String parameterValue) {
443: if (logger.isDebugEnabled())
444: logger.debug("Entering - parameterName = " + parameterName
445: + ", parameterValue = " + parameterValue);
446: init();
447: this .request.addParameter(parameterName, parameterValue);
448: if (logger.isDebugEnabled())
449: logger.debug("Exiting");
450: }
451:
452: /**
453: * Adds an HttpServletRequest parameter that is an array of String values
454: * to be used in setting up the ActionForm instance to be used in this test.
455: * Each parameter added should correspond to an attribute in the ActionForm
456: * instance used by the Action instance being tested.
457: */
458: public void addRequestParameter(String parameterName,
459: String[] parameterValues) {
460: if (logger.isDebugEnabled())
461: logger.debug("Entering - parameterName = " + parameterName
462: + ", parameteValue = " + parameterValues);
463: init();
464: this .request.addParameter(parameterName, parameterValues);
465: if (logger.isDebugEnabled())
466: logger.debug("Exiting");
467: }
468:
469: /**
470: * Sets the request path instructing the ActionServlet to used a
471: * particual ActionMapping.
472: *
473: * @param pathInfo the request path to be processed. This should
474: * correspond to a particular action mapping, as would normally
475: * appear in an HTML or JSP source file.
476: */
477: public void setRequestPathInfo(String pathInfo) {
478: if (logger.isDebugEnabled())
479: logger.debug("Entering - pathInfo = " + pathInfo);
480: init();
481: this .setRequestPathInfo("", pathInfo);
482: if (logger.isDebugEnabled())
483: logger.debug("Exiting");
484: }
485:
486: /**
487: * Sets the request path instructing the ActionServlet to used a
488: * particual ActionMapping. Also sets the ServletPath property
489: * on the request.
490: *
491: * @param moduleName the name of the Struts sub-application with
492: * which this request is associated, or null if it is the default
493: * application.
494: * @param pathInfo the request path to be processed. This should
495: * correspond to a particular action mapping, as would normally
496: * appear in an HTML or JSP source file. If this request is part
497: * of a sub-application, the module name should not appear in the
498: * request path.
499: */
500: public void setRequestPathInfo(String moduleName, String pathInfo) {
501: if (logger.isDebugEnabled())
502: logger.debug("Entering - moduleName = " + moduleName
503: + ", pathInfo = " + pathInfo);
504: init();
505: this .actionPath = Common.stripActionPath(pathInfo);
506: if (moduleName != null) {
507: if (!moduleName.equals("")) {
508: if (!moduleName.startsWith("/"))
509: moduleName = "/" + moduleName;
510: if (!moduleName.endsWith("/"))
511: moduleName = moduleName + "/";
512: }
513: if (logger.isDebugEnabled()) {
514: logger.debug("setting request attribute - name = "
515: + Common.INCLUDE_SERVLET_PATH + ", value = "
516: + moduleName);
517: }
518: this .request.setAttribute(Common.INCLUDE_SERVLET_PATH,
519: moduleName);
520: }
521: this .request.setPathInfo(actionPath);
522: this .requestPathSet = true;
523: if (logger.isDebugEnabled())
524: logger.debug("Exiting");
525: }
526:
527: /**
528: * Sets an initialization parameter on the
529: * ActionServlet. Allows you to simulate an init parameter
530: * that would normally have been found in web.xml,
531: * but is not available while testing with mock objects.
532: * @param key the name of the initialization parameter
533: * @param value the value of the intialization parameter
534: */
535: public void setInitParameter(String key, String value) {
536: if (logger.isDebugEnabled())
537: logger.debug("Entering - key = " + key + ", value = "
538: + value);
539: init();
540: config.setInitParameter(key, value);
541: actionServletIsInitialized = false;
542: if (logger.isDebugEnabled())
543: logger.debug("Exiting");
544: }
545:
546: /**
547: * Sets the context directory to be used with the getRealPath() methods in
548: * the ServletContext and HttpServletRequest API.
549: * @param contextDirectory a File object representing the root context directory
550: * for this application.
551: */
552: public void setContextDirectory(File contextDirectory) {
553: if (logger.isDebugEnabled())
554: logger.debug("Entering - contextDirectory = "
555: + contextDirectory);
556: init();
557: context.setContextDirectory(contextDirectory);
558: actionServletIsInitialized = false;
559: if (logger.isDebugEnabled())
560: logger.debug("Exiting");
561: }
562:
563: /**
564: * Sets the location of the Struts configuration file for the default module.
565: * This method can take either an absolute path, or a relative path. If an
566: * absolute path is supplied, the configuration file will be loaded from the
567: * underlying filesystem; otherwise, the ServletContext loader will be used.
568: */
569: public void setConfigFile(String pathname) {
570: if (logger.isDebugEnabled())
571: logger.debug("Entering - pathName = " + pathname);
572: init();
573: setConfigFile(null, pathname);
574: if (logger.isDebugEnabled())
575: logger.debug("Exiting");
576: }
577:
578: /**
579: * Sets the struts configuration file for a given sub-application. This method
580: * can take either an absolute path, or a relative path. If an absolute path
581: * is supplied, the configuration file will be loaded from the underlying
582: * filesystem; otherwise, the ServletContext loader will be used.
583: *
584: * @param moduleName the name of the sub-application, or null if this is the default application
585: * @param pathname the location of the configuration file for this sub-application
586: */
587: public void setConfigFile(String moduleName, String pathname) {
588: if (logger.isDebugEnabled())
589: logger.debug("Entering - moduleName = " + moduleName
590: + ", pathname =" + pathname);
591: init();
592: if (moduleName == null)
593: this .config.setInitParameter("config", pathname);
594: else
595: this .config.setInitParameter("config/" + moduleName,
596: pathname);
597: actionServletIsInitialized = false;
598: if (logger.isDebugEnabled())
599: logger.debug("Exiting");
600: }
601:
602: /**
603: * Sets the location of the web.xml configuration file to be used
604: * to set up the servlet context and configuration for this test.
605: * This method supports both init-param and context-param tags,
606: * setting the ServletConfig and ServletContext appropriately.
607: * This method can take either an absolute path, or a relative path. If an
608: * absolute path is supplied, the configuration file will be loaded from the
609: * underlying filesystem; otherwise, the ServletContext loader will be used.
610: */
611: public void setServletConfigFile(String pathname) {
612: if (logger.isDebugEnabled())
613: logger.debug("Entering - pathname = " + pathname);
614: init();
615:
616: // pull in the appropriate parts of the
617: // web.xml file -- first the init-parameters
618: Digester digester = new Digester();
619: digester.push(this .config);
620: digester.setValidating(true);
621: digester.addCallMethod("web-app/servlet/init-param",
622: "setInitParameter", 2);
623: digester.addCallParam("web-app/servlet/init-param/param-name",
624: 0);
625: digester.addCallParam("web-app/servlet/init-param/param-value",
626: 1);
627: try {
628: for (int i = 0; i < registrations.length; i += 2) {
629: URL url = context.getResource(registrations[i + 1]);
630: if (url != null)
631: digester.register(registrations[i], url.toString());
632: }
633: InputStream input = context.getResourceAsStream(pathname);
634: if (input == null)
635: throw new AssertionFailedError("Invalid pathname: "
636: + pathname);
637: digester.parse(input);
638: input.close();
639: } catch (Exception e) {
640: throw new AssertionFailedError(
641: "Received an exception while loading web.xml - "
642: + e.getClass() + " : " + e.getMessage());
643: }
644:
645: // now the context parameters..
646: digester = new Digester();
647: digester.setValidating(true);
648: digester.push(this .context);
649: digester.addCallMethod("web-app/context-param",
650: "setInitParameter", 2);
651: digester.addCallParam("web-app/context-param/param-name", 0);
652: digester.addCallParam("web-app/context-param/param-value", 1);
653: try {
654: for (int i = 0; i < registrations.length; i += 2) {
655: URL url = context.getResource(registrations[i + 1]);
656: if (url != null)
657: digester.register(registrations[i], url.toString());
658: }
659: InputStream input = context.getResourceAsStream(pathname);
660: if (input == null)
661: throw new AssertionFailedError("Invalid pathname: "
662: + pathname);
663: digester.parse(input);
664: input.close();
665: } catch (Exception e) {
666: throw new AssertionFailedError(
667: "Received an exception while loading web.xml - "
668: + e.getClass() + " : " + e.getMessage());
669: }
670: actionServletIsInitialized = false;
671: if (logger.isDebugEnabled())
672: logger.debug("Exiting");
673: }
674:
675: /**
676: * Returns the forward sent to RequestDispatcher.
677: */
678: protected String getActualForward() {
679: if (logger.isDebugEnabled())
680: logger.debug("Entering");
681: if (response.containsHeader("Location")) {
682: return Common.stripJSessionID(response
683: .getHeader("Location"));
684: } else
685: try {
686: String strippedForward = request.getContextPath()
687: + Common
688: .stripJSessionID(((ServletContextSimulator) config
689: .getServletContext())
690: .getRequestDispatcherSimulator()
691: .getForward());
692: if (logger.isDebugEnabled()) {
693: logger
694: .debug("stripped forward and added context path - "
695: + strippedForward);
696: }
697: if (logger.isDebugEnabled())
698: logger.debug("Exiting");
699: return strippedForward;
700: } catch (NullPointerException npe) {
701: if (logger.isDebugEnabled()) {
702: logger
703: .debug(
704: "caught NullPointerException - returning null",
705: npe);
706: }
707: return null;
708: }
709: }
710:
711: /**
712: * Verifies if the ActionServlet controller used this forward.
713: *
714: * @param forwardName the logical name of a forward, as defined
715: * in the Struts configuration file. This can either refer to a
716: * global forward, or one local to the ActionMapping.
717: *
718: * @exception AssertionFailedError if the ActionServlet controller
719: * used a different forward than <code>forwardName</code> after
720: * executing an Action object.
721: */
722: public void verifyForward(String forwardName)
723: throws AssertionFailedError {
724: if (logger.isDebugEnabled())
725: logger.debug("Entering - forwardName = " + forwardName);
726: init();
727: Common.verifyForwardPath(actionPath, forwardName,
728: getActualForward(), false, request, config
729: .getServletContext(), config);
730: if (logger.isDebugEnabled())
731: logger.debug("Exiting");
732: }
733:
734: /**
735: * Verifies if the ActionServlet controller used this actual path
736: * as a forward.
737: *
738: * @param forwardPath an absolute pathname to which the request
739: * is to be forwarded.
740: *
741: * @exception AssertionFailedError if the ActionServlet controller
742: * used a different forward path than <code>forwardPath</code> after
743: * executing an Action object.
744: */
745: public void verifyForwardPath(String forwardPath)
746: throws AssertionFailedError {
747: if (logger.isDebugEnabled())
748: logger.debug("Entering - forwardPath = " + forwardPath);
749: init();
750: String actualForward = getActualForward();
751: if ((actualForward == null) && (forwardPath == null)) {
752: // actions can send null forwards, which is fine.
753: return;
754: }
755:
756: forwardPath = request.getContextPath() + forwardPath;
757:
758: if (actualForward == null) {
759: if (logger.isDebugEnabled()) {
760: logger
761: .debug("actualForward is null - this usually means it is not mapped properly.");
762: }
763: throw new AssertionFailedError(
764: "Was expecting '"
765: + forwardPath
766: + "' but it appears the Action has tried to return an ActionForward that is not mapped correctly.");
767: }
768: if (logger.isDebugEnabled()) {
769: logger.debug("expected forward = '" + forwardPath
770: + "' - actual forward = '" + actualForward + "'");
771: }
772: if (!(actualForward.equals(forwardPath)))
773: throw new AssertionFailedError("was expecting '"
774: + forwardPath + "' but received '" + actualForward
775: + "'");
776: if (logger.isDebugEnabled())
777: logger.debug("Exiting");
778: }
779:
780: /**
781: * Verifies if the ActionServlet controller forwarded to the defined
782: * input path.
783: *
784: * @exception AssertionFailedError if the ActionServlet controller
785: * used a different forward than the defined input path after
786: * executing an Action object.
787: */
788: public void verifyInputForward() {
789: if (logger.isDebugEnabled())
790: logger.debug("Entering");
791: init();
792: Common.verifyForwardPath(actionPath, null, getActualForward(),
793: true, request, config.getServletContext(), config);
794: if (logger.isDebugEnabled())
795: logger.debug("Exiting");
796: }
797:
798: /**
799: * Verifies that the ActionServlet controller used this forward and Tiles definition.
800: *
801: * @param forwardName the logical name of a forward, as defined
802: * in the Struts configuration file. This can either refer to a
803: * global forward, or one local to the ActionMapping.
804: *
805: * @param definitionName the name of a Tiles definition, as defined
806: * in the Tiles configuration file.
807: *
808: * @exception AssertionFailedError if the ActionServlet controller
809: * used a different forward or tiles definition than those given after
810: * executing an Action object.
811: */
812: public void verifyTilesForward(String forwardName,
813: String definitionName) {
814: if (logger.isTraceEnabled())
815: logger.trace("Entering - forwardName=" + forwardName
816: + ", definitionName=" + definitionName);
817: init();
818: Common.verifyTilesForward(actionPath, forwardName,
819: definitionName, false, request, config
820: .getServletContext(), config);
821: if (logger.isTraceEnabled())
822: logger.trace("Exiting");
823: }
824:
825: /**
826: * Verifies that the ActionServlet controller forwarded to the defined
827: * input Tiles definition.
828: *
829: * @param definitionName the name of a Tiles definition, as defined
830: * in the Tiles configuration file.
831: *
832: * @exception AssertionFailedError if the ActionServlet controller
833: * used a different forward than the defined input path after
834: * executing an Action object.
835: */
836: public void verifyInputTilesForward(String definitionName) {
837: if (logger.isTraceEnabled())
838: logger.trace("Entering - definitionName=" + definitionName);
839: init();
840: Common.verifyTilesForward(actionPath, null, definitionName,
841: true, request, config.getServletContext(), config);
842: if (logger.isTraceEnabled())
843: logger.trace("Exiting");
844: }
845:
846: /**
847: * Verifies if the ActionServlet controller sent these error messages.
848: * There must be an exact match between the provided error messages, and
849: * those sent by the controller, in both name and number.
850: *
851: * @param errorNames a String array containing the error message keys
852: * to be verified, as defined in the application resource properties
853: * file.
854: *
855: * @exception AssertionFailedError if the ActionServlet controller
856: * sent different error messages than those in <code>errorNames</code>
857: * after executing an Action object.
858: */
859:
860: public void verifyActionErrors(String[] errorNames) {
861: if (logger.isDebugEnabled())
862: logger.debug("errorNames = " + errorNames);
863: init();
864: Common.verifyActionMessages(request, errorNames,
865: Globals.ERROR_KEY, "error");
866: if (logger.isDebugEnabled())
867: logger.debug("Exiting");
868: }
869:
870: /**
871: * Verifies that the ActionServlet controller sent no error messages upon
872: * executing an Action object.
873: *
874: * @exception AssertionFailedError if the ActionServlet controller
875: * sent any error messages after excecuting and Action object.
876: */
877: public void verifyNoActionErrors() {
878: if (logger.isDebugEnabled())
879: logger.debug("Entering");
880: init();
881: Common.verifyNoActionMessages(request, Globals.ERROR_KEY,
882: "error");
883: if (logger.isDebugEnabled())
884: logger.debug("Exiting");
885: }
886:
887: /**
888: * Verifies if the ActionServlet controller sent these action messages.
889: * There must be an exact match between the provided action messages, and
890: * those sent by the controller, in both name and number.
891: *
892: * @param messageNames a String array containing the action message keys
893: * to be verified, as defined in the application resource properties
894: * file.
895: *
896: * @exception AssertionFailedError if the ActionServlet controller
897: * sent different action messages than those in <code>messageNames</code>
898: * after executing an Action object.
899: */
900: public void verifyActionMessages(String[] messageNames) {
901: if (logger.isDebugEnabled())
902: logger.debug("Entering - messageNames = " + messageNames);
903: init();
904: Common.verifyActionMessages(request, messageNames,
905: Globals.MESSAGE_KEY, "action");
906: if (logger.isDebugEnabled())
907: logger.debug("Exiting");
908: }
909:
910: /**
911: * Verifies that the ActionServlet controller sent no action messages upon
912: * executing an Action object.
913: *
914: * @exception AssertionFailedError if the ActionServlet controller
915: * sent any action messages after excecuting and Action object.
916: */
917: public void verifyNoActionMessages() {
918: if (logger.isDebugEnabled())
919: logger.debug("Entering");
920: init();
921: Common.verifyNoActionMessages(request, Globals.MESSAGE_KEY,
922: "action");
923: if (logger.isDebugEnabled())
924: logger.debug("Exiting");
925: }
926:
927: /**
928: * Returns the ActionForm instance stored in either the request or session. Note
929: * that no form will be returned if the Action being tested cleans up the form
930: * instance.
931: *
932: * @ return the ActionForm instance used in this test, or null if it does not exist.
933: */
934: public ActionForm getActionForm() {
935: if (logger.isDebugEnabled())
936: logger.debug("Entering");
937: init();
938: if (logger.isDebugEnabled())
939: logger.debug("Exiting");
940: return Common.getActionForm(actionPath, request, context);
941: }
942:
943: /**
944: * Sets an ActionForm instance to be used in this test. The given ActionForm instance
945: * will be stored in the scope specified in the Struts configuration file (ie: request
946: * or session). Note that while this ActionForm instance is passed to the test, Struts
947: * will still control how it is used. In particular, it will call the ActionForm.reset()
948: * method, so if you override this method in your ActionForm subclass, you could potentially
949: * reset attributes in the form passed through this method.
950: *
951: * @param form the ActionForm instance to be used in this test.
952: */
953: public void setActionForm(ActionForm form) {
954: if (logger.isDebugEnabled())
955: logger.debug("Entering - form = " + form);
956: init();
957: // make sure action servlet is intialized
958: getActionServlet();
959: Common.setActionForm(form, request, actionPath, context);
960: if (logger.isDebugEnabled())
961: logger.debug("Exiting");
962: }
963:
964: }
|