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