Source Code Cross Referenced for AbstractFlowExecutionTests.java in  » Workflow-Engines » spring-webflow-1.0.4 » org » springframework » webflow » test » execution » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Workflow Engines » spring webflow 1.0.4 » org.springframework.webflow.test.execution 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2004-2007 the original author or authors.
003:         *
004:         * Licensed under the Apache License, Version 2.0 (the "License");
005:         * you may not use this file except in compliance with the License.
006:         * You may obtain a copy of the License at
007:         *
008:         *      http://www.apache.org/licenses/LICENSE-2.0
009:         *
010:         * Unless required by applicable law or agreed to in writing, software
011:         * distributed under the License is distributed on an "AS IS" BASIS,
012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013:         * See the License for the specific language governing permissions and
014:         * limitations under the License.
015:         */
016:        package org.springframework.webflow.test.execution;
017:
018:        import java.util.Collection;
019:        import java.util.Map;
020:
021:        import junit.framework.TestCase;
022:
023:        import org.springframework.binding.expression.ExpressionParser;
024:        import org.springframework.core.style.StylerUtils;
025:        import org.springframework.util.Assert;
026:        import org.springframework.webflow.context.ExternalContext;
027:        import org.springframework.webflow.core.DefaultExpressionParserFactory;
028:        import org.springframework.webflow.core.collection.MutableAttributeMap;
029:        import org.springframework.webflow.core.collection.ParameterMap;
030:        import org.springframework.webflow.definition.FlowDefinition;
031:        import org.springframework.webflow.engine.impl.FlowExecutionImplFactory;
032:        import org.springframework.webflow.execution.FlowExecution;
033:        import org.springframework.webflow.execution.FlowExecutionException;
034:        import org.springframework.webflow.execution.FlowExecutionFactory;
035:        import org.springframework.webflow.execution.ViewSelection;
036:        import org.springframework.webflow.execution.support.ApplicationView;
037:        import org.springframework.webflow.execution.support.ExternalRedirect;
038:        import org.springframework.webflow.execution.support.FlowDefinitionRedirect;
039:        import org.springframework.webflow.execution.support.FlowExecutionRedirect;
040:        import org.springframework.webflow.test.MockExternalContext;
041:
042:        /**
043:         * Base class for integration tests that verify a flow executes as expected.
044:         * Flow execution tests captured by subclasses should test that a flow responds
045:         * to all supported transition criteria correctly, transitioning to the correct
046:         * states and producing the expected results on the occurence of possible
047:         * external (user) events.
048:         * <p>
049:         * More specifically, a typical flow execution test case will test:
050:         * <ul>
051:         * <li>That the flow execution starts as expected given a request from an
052:         * external context containing potential input attributes (see the
053:         * {@link #startFlow(MutableAttributeMap, ExternalContext)} variants).
054:         * <li>That given the set of supported state transition criteria a state
055:         * executes the appropriate transition when a matching event is signaled (with
056:         * potential input request parameters, see the
057:         * {@link #signalEvent(String, ExternalContext)} variants). A test case should
058:         * be coded for each logical event that can occur, where an event drives a
059:         * possible path through the flow. The goal should be to exercise all possible
060:         * paths of the flow. Use a test coverage tool like Clover or Emma to assist
061:         * with measuring your test's effectiveness.
062:         * <li>That given a transition that leads to an interactive state type (a view
063:         * state or an end state) that the view selection returned to the client matches
064:         * what was expected and the current state of the flow matches what is expected.
065:         * </ul>
066:         * <p>
067:         * A flow execution test can effectively automate and validate the orchestration
068:         * required to drive an end-to-end business task that spans several steps
069:         * involving the user to complete. Such tests are a good way to test your system
070:         * top-down starting at the web-tier and pushing through all the way to the DB
071:         * without having to deploy to a servlet or portlet container. In addition, they
072:         * can be used to effectively test a flow's execution (the web layer)
073:         * standalone, typically with a mock service layer. Both styles of testing are
074:         * valuable and supported.
075:         * 
076:         * @author Keith Donald
077:         */
078:        public abstract class AbstractFlowExecutionTests extends TestCase {
079:
080:            /**
081:             * The factory that will create the flow execution to test.
082:             */
083:            private FlowExecutionFactory flowExecutionFactory;
084:
085:            /**
086:             * The expression parser for parsing evaluatable model attribute
087:             * expressions.
088:             */
089:            private ExpressionParser expressionParser = DefaultExpressionParserFactory
090:                    .getExpressionParser();
091:
092:            /**
093:             * The flow execution running the flow when the test is active (runtime
094:             * object).
095:             */
096:            private FlowExecution flowExecution;
097:
098:            /**
099:             * Constructs a default flow execution test.
100:             * @see #setName(String)
101:             */
102:            public AbstractFlowExecutionTests() {
103:                super ();
104:            }
105:
106:            /**
107:             * Constructs a flow execution test with given name.
108:             * @param name the name of the test
109:             * @since 1.0.2
110:             */
111:            public AbstractFlowExecutionTests(String name) {
112:                super (name);
113:            }
114:
115:            /**
116:             * Set the expression parser responsible for parsing expression strings into
117:             * evaluatable expression objects.
118:             */
119:            public void setExpressionParser(ExpressionParser expressionParser) {
120:                Assert.notNull(expressionParser,
121:                        "The expression parser is required");
122:                this .expressionParser = expressionParser;
123:            }
124:
125:            /**
126:             * Gets the factory that will create the flow execution to test. This method
127:             * will create the factory if it is not already set.
128:             * @return the flow execution factory
129:             * @see #createFlowExecutionFactory()
130:             */
131:            protected FlowExecutionFactory getFlowExecutionFactory() {
132:                if (flowExecutionFactory == null) {
133:                    flowExecutionFactory = createFlowExecutionFactory();
134:                }
135:                return flowExecutionFactory;
136:            }
137:
138:            /**
139:             * Creates an ExternalContext instance. Defaults to using {@link MockExternalContext}.
140:             * Subclasses can override if they which to use another external context
141:             * implementation.
142:             * @param requestParameters request parameters to put into the
143:             * external context (optional)
144:             * @return a new ExternalContext instance
145:             */
146:            protected ExternalContext createExternalContext(
147:                    ParameterMap requestParameters) {
148:                return new MockExternalContext(requestParameters);
149:            }
150:
151:            /**
152:             * Start the flow execution to be tested.
153:             * <p>
154:             * Convenience operation that starts the execution with:
155:             * <ul>
156:             * <li>no input attributes
157:             * <li>an empty {@link ExternalContext} with no environmental request
158:             * parameters set
159:             * </ul>
160:             * @return the view selection made as a result of starting the flow
161:             * (returned when the first interactive state (a view state or end state) is
162:             * entered)
163:             * @throws FlowExecutionException if an exception was thrown while starting
164:             * the flow execution
165:             */
166:            protected ViewSelection startFlow() throws FlowExecutionException {
167:                return startFlow(null, createExternalContext(null));
168:            }
169:
170:            /**
171:             * Start the flow execution to be tested.
172:             * <p>
173:             * Convenience operation that starts the execution with:
174:             * <ul>
175:             * <li>the specified input attributes, eligible for mapping by the root
176:             * flow
177:             * <li>an empty {@link ExternalContext} with no environmental request
178:             * parameters set
179:             * </ul>
180:             * @param input the flow execution input attributes eligible for mapping by
181:             * the root flow
182:             * @return the view selection made as a result of starting the flow
183:             * (returned when the first interactive state (a view state or end state) is
184:             * entered)
185:             * @throws FlowExecutionException if an exception was thrown while starting
186:             * the flow execution
187:             */
188:            protected ViewSelection startFlow(MutableAttributeMap input)
189:                    throws FlowExecutionException {
190:                return startFlow(input, createExternalContext(null));
191:            }
192:
193:            /**
194:             * Start the flow execution to be tested.
195:             * <p>
196:             * This is the most flexible of the start methods. It allows you to specify:
197:             * <ol>
198:             * <li>a map of input attributes to pass to the flow execution, eligible
199:             * for mapping by the root flow definition
200:             * <li>an external context that provides the flow execution being tested
201:             * access to the calling environment for this request
202:             * </ol>
203:             * @param input the flow execution input attributes eligible for mapping by
204:             * the root flow
205:             * @param context the external context providing information about the
206:             * caller's environment, used by the flow execution during the start
207:             * operation
208:             * @return the view selection made as a result of starting the flow
209:             * (returned when the first interactive state (a view state or end state) is
210:             * entered)
211:             * @throws FlowExecutionException if an exception was thrown while starting
212:             * the flow execution
213:             */
214:            protected ViewSelection startFlow(MutableAttributeMap input,
215:                    ExternalContext context) throws FlowExecutionException {
216:                flowExecution = getFlowExecutionFactory().createFlowExecution(
217:                        getFlowDefinition());
218:                return flowExecution.start(input, context);
219:            }
220:
221:            /**
222:             * Signal an occurence of an event in the current state of the flow
223:             * execution being tested.
224:             * @param eventId the event that occured
225:             * @throws FlowExecutionException if an exception was thrown within a state
226:             * of the resumed flow execution during event processing
227:             */
228:            protected ViewSelection signalEvent(String eventId)
229:                    throws FlowExecutionException {
230:                return signalEvent(eventId, createExternalContext(null));
231:            }
232:
233:            /**
234:             * Signal an occurence of an event in the current state of the flow
235:             * execution being tested.
236:             * @param eventId the event that occured
237:             * @param requestParameters request parameters needed by the flow execution
238:             * to complete event processing
239:             * @throws FlowExecutionException if an exception was thrown within a state
240:             * of the resumed flow execution during event processing
241:             */
242:            protected ViewSelection signalEvent(String eventId,
243:                    ParameterMap requestParameters)
244:                    throws FlowExecutionException {
245:                return signalEvent(eventId,
246:                        createExternalContext(requestParameters));
247:            }
248:
249:            /**
250:             * Signal an occurence of an event in the current state of the flow
251:             * execution being tested.
252:             * <p>
253:             * Note: signaling an event will cause state transitions to occur in a chain
254:             * until control is returned to the caller. Control is returned once an
255:             * "interactive" state type is entered: either a view state when the flow is
256:             * paused or an end state when the flow terminates. Action states are
257:             * executed without returning control, as their result always triggers
258:             * another state transition, executed internally. Action states can also be
259:             * executed in a chain like fashion (e.g. action state 1 (result), action
260:             * state 2 (result), action state 3 (result), view state <control returns so
261:             * view can be rendered>).
262:             * <p>
263:             * If you wish to verify expected behavior on each state transition (and not
264:             * just when the view state triggers return of control back to the client),
265:             * you have a few options:
266:             * <p>
267:             * First, you may implement standalone unit tests for your
268:             * {@link org.springframework.webflow.execution.Action} implementations.
269:             * There you can verify that an Action executes its logic properly in
270:             * isolation. When you do this, you may mock or stub out services the Action
271:             * implementation needs that are expensive to initialize. You can also
272:             * verify there that the action puts everything in the flow or request scope
273:             * it was expected to (to meet its contract with the view it is prepping for
274:             * display, for example).
275:             * <p>
276:             * Second, you can attach one or more FlowExecutionListeners to the flow
277:             * execution at start time within your test code, which will allow you to
278:             * receive a callback on each state transition (among other points). It is
279:             * recommended you extend
280:             * {@link org.springframework.webflow.execution.FlowExecutionListenerAdapter}
281:             * and only override the callback methods you are interested in.
282:             * @param eventId the event that occured
283:             * @param context the external context providing information about the
284:             * caller's environment, used by the flow execution during the signal event
285:             * operation
286:             * @return the view selection that was made, returned once control is
287:             * returned to the client (occurs when the flow enters a view state, or an
288:             * end state)
289:             * @throws FlowExecutionException if an exception was thrown within a state
290:             * of the resumed flow execution during event processing
291:             */
292:            protected ViewSelection signalEvent(String eventId,
293:                    ExternalContext context) throws FlowExecutionException {
294:                Assert
295:                        .state(
296:                                flowExecution != null,
297:                                "The flow execution to test is [null]; "
298:                                        + "you must start the flow execution before you can signal an event against it!");
299:                return flowExecution.signalEvent(eventId, context);
300:            }
301:
302:            /**
303:             * Refresh the flow execution being tested, asking the current view state to
304:             * make a "refresh" view selection. This is idempotent operation that may be
305:             * safely called on an active but currently paused execution. Used to
306:             * simulate a browser flow execution redirect.
307:             * @return the current view selection for this flow execution
308:             * @throws FlowExecutionException if an exception was thrown during refresh
309:             */
310:            protected ViewSelection refresh() throws FlowExecutionException {
311:                return refresh(createExternalContext(null));
312:            }
313:
314:            /**
315:             * Refresh the flow execution being tested, asking the current view state
316:             * state to make a "refresh" view selection. This is idempotent operation
317:             * that may be safely called on an active but currently paused execution.
318:             * Used to simulate a browser flow execution redirect.
319:             * @param context the external context providing information about the
320:             * caller's environment, used by the flow execution during the refresh
321:             * operation
322:             * @return the current view selection for this flow execution
323:             * @throws FlowExecutionException if an exception was thrown during refresh
324:             */
325:            protected ViewSelection refresh(ExternalContext context)
326:                    throws FlowExecutionException {
327:                Assert
328:                        .state(
329:                                flowExecution != null,
330:                                "The flow execution to test is [null]; you must start the flow execution before you can refresh it!");
331:                return flowExecution.refresh(context);
332:            }
333:
334:            // convenience accessors
335:
336:            /**
337:             * Returns the flow execution being tested.
338:             * @return the flow execution
339:             * @throws IllegalStateException the execution has not been started
340:             */
341:            protected FlowExecution getFlowExecution()
342:                    throws IllegalStateException {
343:                Assert
344:                        .state(
345:                                flowExecution != null,
346:                                "The flow execution to test is [null]; you must start the flow execution before you can query it!");
347:                return flowExecution;
348:            }
349:
350:            /**
351:             * Returns the attribute in conversation scope. Conversation-scoped
352:             * attributes are shared by all flow sessions.
353:             * @param attributeName the name of the attribute
354:             * @return the attribute value
355:             */
356:            protected Object getConversationAttribute(String attributeName) {
357:                return getFlowExecution().getConversationScope().get(
358:                        attributeName);
359:            }
360:
361:            /**
362:             * Returns the required attribute in conversation scope; asserts the
363:             * attribute is present. Conversation-scoped attributes are shared by all
364:             * flow sessions.
365:             * @param attributeName the name of the attribute
366:             * @return the attribute value
367:             * @throws IllegalStateException if the attribute was not present
368:             */
369:            protected Object getRequiredConversationAttribute(
370:                    String attributeName) throws IllegalStateException {
371:                return getFlowExecution().getConversationScope().getRequired(
372:                        attributeName);
373:            }
374:
375:            /**
376:             * Returns the required attribute in conversation scope; asserts the
377:             * attribute is present and of the required type. Conversation-scoped
378:             * attributes are shared by all flow sessions.
379:             * @param attributeName the name of the attribute
380:             * @return the attribute value
381:             * @throws IllegalStateException if the attribute was not present or not of
382:             * the required type
383:             */
384:            protected Object getRequiredConversationAttribute(
385:                    String attributeName, Class requiredType)
386:                    throws IllegalStateException {
387:                return getFlowExecution().getConversationScope().getRequired(
388:                        attributeName, requiredType);
389:            }
390:
391:            /**
392:             * Returns the attribute in flow scope. Flow-scoped attributes are local to
393:             * the active flow session.
394:             * @param attributeName the name of the attribute
395:             * @return the attribute value
396:             */
397:            protected Object getFlowAttribute(String attributeName) {
398:                return getFlowExecution().getActiveSession().getScope().get(
399:                        attributeName);
400:            }
401:
402:            /**
403:             * Returns the required attribute in flow scope; asserts the attribute is
404:             * present. Flow-scoped attributes are local to the active flow session.
405:             * @param attributeName the name of the attribute
406:             * @return the attribute value
407:             * @throws IllegalStateException if the attribute was not present
408:             */
409:            protected Object getRequiredFlowAttribute(String attributeName)
410:                    throws IllegalStateException {
411:                return getFlowExecution().getActiveSession().getScope()
412:                        .getRequired(attributeName);
413:            }
414:
415:            /**
416:             * Returns the required attribute in flow scope; asserts the attribute is
417:             * present and of the correct type. Flow-scoped attributes are local to the
418:             * active flow session.
419:             * @param attributeName the name of the attribute
420:             * @return the attribute value
421:             * @throws IllegalStateException if the attribute was not present or was of
422:             * the wrong type
423:             */
424:            protected Object getRequiredFlowAttribute(String attributeName,
425:                    Class requiredType) throws IllegalStateException {
426:                return getFlowExecution().getActiveSession().getScope()
427:                        .getRequired(attributeName, requiredType);
428:            }
429:
430:            /**
431:             * Returns the attribute in flash scope. Flash-scoped attributes are local to
432:             * the active flow session and cleared on the next user event.
433:             * @param attributeName the name of the attribute
434:             * @return the attribute value
435:             * @since 1.0.2
436:             */
437:            protected Object getFlashAttribute(String attributeName) {
438:                return getFlowExecution().getActiveSession().getFlashMap().get(
439:                        attributeName);
440:            }
441:
442:            /**
443:             * Returns the required attribute in flash scope; asserts the attribute is
444:             * present. Flash-scoped attributes are local to the active flow session and cleared on
445:             * the next user event.
446:             * @param attributeName the name of the attribute
447:             * @return the attribute value
448:             * @throws IllegalStateException if the attribute was not present
449:             * @since 1.0.2
450:             */
451:            protected Object getRequiredFlashAttribute(String attributeName)
452:                    throws IllegalStateException {
453:                return getFlowExecution().getActiveSession().getFlashMap()
454:                        .getRequired(attributeName);
455:            }
456:
457:            /**
458:             * Returns the required attribute in flash scope; asserts the attribute is
459:             * present and of the correct type. Flash-scoped attributes are local to the
460:             * active flow session and cleared on the next user event.
461:             * @param attributeName the name of the attribute
462:             * @return the attribute value
463:             * @throws IllegalStateException if the attribute was not present or was of
464:             * the wrong type
465:             */
466:            protected Object getRequiredFlashAttribute(String attributeName,
467:                    Class requiredType) throws IllegalStateException {
468:                return getFlowExecution().getActiveSession().getFlashMap()
469:                        .getRequired(attributeName, requiredType);
470:            }
471:
472:            // assert helpers
473:
474:            /**
475:             * Assert that the active flow session is for the flow with the provided id.
476:             * @param expectedActiveFlowId the flow id that should have a session active
477:             * in the tested flow execution
478:             */
479:            protected void assertActiveFlowEquals(String expectedActiveFlowId) {
480:                assertEquals("The active flow id '"
481:                        + getFlowExecution().getActiveSession().getDefinition()
482:                                .getId()
483:                        + "' does not equal the expected active flow id '"
484:                        + expectedActiveFlowId + "'", expectedActiveFlowId,
485:                        getFlowExecution().getActiveSession().getDefinition()
486:                                .getId());
487:            }
488:
489:            /**
490:             * Assert that the entire flow execution is active; that is, it has not
491:             * ended and has been started.
492:             */
493:            protected void assertFlowExecutionActive() {
494:                assertTrue("The flow execution is not active but it should be",
495:                        getFlowExecution().isActive());
496:            }
497:
498:            /**
499:             * Assert that the entire flow execution has ended; that is, it is no longer
500:             * active.
501:             */
502:            protected void assertFlowExecutionEnded() {
503:                assertTrue(
504:                        "The flow execution is still active but it should have ended",
505:                        !getFlowExecution().isActive());
506:            }
507:
508:            /**
509:             * Assert that the current state of the flow execution equals the provided
510:             * state id.
511:             * @param expectedCurrentStateId the expected current state
512:             */
513:            protected void assertCurrentStateEquals(
514:                    String expectedCurrentStateId) {
515:                assertEquals("The current state '"
516:                        + getFlowExecution().getActiveSession().getState()
517:                                .getId()
518:                        + "' does not equal the expected state '"
519:                        + expectedCurrentStateId + "'", expectedCurrentStateId,
520:                        getFlowExecution().getActiveSession().getState()
521:                                .getId());
522:            }
523:
524:            /**
525:             * Assert that the view name equals the provided value.
526:             * @param expectedViewName the expected name
527:             * @param viewSelection the selected view
528:             */
529:            protected void assertViewNameEquals(String expectedViewName,
530:                    ApplicationView viewSelection) {
531:                assertEquals("The view name is wrong:", expectedViewName,
532:                        viewSelection.getViewName());
533:            }
534:
535:            /**
536:             * Assert that the selected view contains the specified model attribute with
537:             * the provided expected value.
538:             * @param expectedValue the expected value
539:             * @param attributeName the attribute name (can be an expression)
540:             * @param viewSelection the selected view with a model attribute map to
541:             * assert against
542:             */
543:            protected void assertModelAttributeEquals(Object expectedValue,
544:                    String attributeName, ApplicationView viewSelection) {
545:                assertEquals("The model attribute '" + attributeName
546:                        + "' value is wrong:", expectedValue,
547:                        evaluateModelAttributeExpression(attributeName,
548:                                viewSelection.getModel()));
549:            }
550:
551:            /**
552:             * Assert that the selected view contains the specified collection model
553:             * attribute with the provided expected size.
554:             * @param expectedSize the expected size
555:             * @param attributeName the collection attribute name (can be an expression
556:             * @param viewSelection the selected view with a model attribute map to
557:             * assert against
558:             */
559:            protected void assertModelAttributeCollectionSize(int expectedSize,
560:                    String attributeName, ApplicationView viewSelection) {
561:                assertModelAttributeNotNull(attributeName, viewSelection);
562:                Collection c = (Collection) evaluateModelAttributeExpression(
563:                        attributeName, viewSelection.getModel());
564:                assertEquals("The model attribute '" + attributeName
565:                        + "' collection size is wrong:", expectedSize, c.size());
566:            }
567:
568:            /**
569:             * Assert that the selected view contains the specified model attribute.
570:             * @param attributeName the attribute name (can be an expression)
571:             * @param viewSelection the selected view with a model attribute map to
572:             * assert against
573:             */
574:            protected void assertModelAttributeNotNull(String attributeName,
575:                    ApplicationView viewSelection) {
576:                assertNotNull("The model attribute '" + attributeName
577:                        + "' is null but should not be; model contents are "
578:                        + StylerUtils.style(viewSelection.getModel()),
579:                        evaluateModelAttributeExpression(attributeName,
580:                                viewSelection.getModel()));
581:            }
582:
583:            /**
584:             * Assert that the selected view does not contain the specified model
585:             * attribute.
586:             * @param attributeName the attribute name (can be an expression)
587:             * @param viewSelection the selected view with a model attribute map to
588:             * assert against
589:             */
590:            protected void assertModelAttributeNull(String attributeName,
591:                    ApplicationView viewSelection) {
592:                assertNull("The model attribute '" + attributeName
593:                        + "' is not null but should be; model contents are "
594:                        + StylerUtils.style(viewSelection.getModel()),
595:                        evaluateModelAttributeExpression(attributeName,
596:                                viewSelection.getModel()));
597:            }
598:
599:            // other helpers
600:
601:            /**
602:             * Assert that the returned view selection is an instance of
603:             * {@link ApplicationView}.
604:             * @param viewSelection the view selection
605:             */
606:            protected ApplicationView applicationView(
607:                    ViewSelection viewSelection) {
608:                Assert.isInstanceOf(ApplicationView.class, viewSelection,
609:                        "Unexpected class of view selection: ");
610:                return (ApplicationView) viewSelection;
611:            }
612:
613:            /**
614:             * Assert that the returned view selection is an instance of
615:             * {@link FlowExecutionRedirect}.
616:             * @param viewSelection the view selection
617:             */
618:            protected FlowExecutionRedirect flowExecutionRedirect(
619:                    ViewSelection viewSelection) {
620:                Assert.isInstanceOf(FlowExecutionRedirect.class, viewSelection,
621:                        "Unexpected class of view selection: ");
622:                return (FlowExecutionRedirect) viewSelection;
623:            }
624:
625:            /**
626:             * Assert that the returned view selection is an instance of
627:             * {@link FlowDefinitionRedirect}.
628:             * @param viewSelection the view selection
629:             */
630:            protected FlowDefinitionRedirect flowDefinitionRedirect(
631:                    ViewSelection viewSelection) {
632:                Assert.isInstanceOf(FlowDefinitionRedirect.class,
633:                        viewSelection, "Unexpected class of view selection: ");
634:                return (FlowDefinitionRedirect) viewSelection;
635:            }
636:
637:            /**
638:             * Assert that the returned view selection is an instance of
639:             * {@link ExternalRedirect}.
640:             * @param viewSelection the view selection
641:             */
642:            protected ExternalRedirect externalRedirect(
643:                    ViewSelection viewSelection) {
644:                Assert.isInstanceOf(ExternalRedirect.class, viewSelection,
645:                        "Unexpected class of view selection: ");
646:                return (ExternalRedirect) viewSelection;
647:            }
648:
649:            /**
650:             * Assert that the returned view selection is the
651:             * {@link ViewSelection#NULL_VIEW}.
652:             * @param viewSelection the view selection
653:             */
654:            protected void nullView(ViewSelection viewSelection) {
655:                assertEquals("Not the null view selection:", viewSelection,
656:                        ViewSelection.NULL_VIEW);
657:            }
658:
659:            /**
660:             * Evaluates a model attribute expression.
661:             * @param attributeName the attribute expression
662:             * @param model the model map
663:             * @return the attribute expression value
664:             */
665:            protected Object evaluateModelAttributeExpression(
666:                    String attributeName, Map model) {
667:                return expressionParser.parseExpression(attributeName)
668:                        .evaluate(model, null);
669:            }
670:
671:            /**
672:             * Factory method to create the flow execution factory. Subclasses
673:             * could override this if they want to use a custom flow execution factory
674:             * or custom configuration of the flow execution factory, registering
675:             * flow execution listeners for instance.
676:             * The default implementation just returns a {@link FlowExecutionImplFactory}
677:             * instance.
678:             * @return the flow execution factory
679:             */
680:            protected FlowExecutionFactory createFlowExecutionFactory() {
681:                return new FlowExecutionImplFactory();
682:            }
683:
684:            /**
685:             * Directly update the flow execution used by the test by setting
686:             * it to given flow execution. Use this if you have somehow manipulated
687:             * the flow execution being tested and want to continue the test
688:             * with another flow execution.
689:             * @param flowExecution the flow execution to use
690:             */
691:            protected void updateFlowExecution(FlowExecution flowExecution) {
692:                this .flowExecution = flowExecution;
693:            }
694:
695:            /**
696:             * Returns the flow definition to be tested. Subclasses must implement.
697:             * @return the flow definition
698:             */
699:            protected abstract FlowDefinition getFlowDefinition();
700:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.