001: // Copyright 2006, 2007 The Apache Software Foundation
002: //
003: // Licensed under the Apache License, Version 2.0 (the "License");
004: // you may not use this file except in compliance with the License.
005: // You may obtain a copy of the License at
006: //
007: // http://www.apache.org/licenses/LICENSE-2.0
008: //
009: // Unless required by applicable law or agreed to in writing, software
010: // distributed under the License is distributed on an "AS IS" BASIS,
011: // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: // See the License for the specific language governing permissions and
013: // limitations under the License.
014:
015: package org.apache.tapestry.ioc.test;
016:
017: import org.easymock.EasyMock;
018: import org.easymock.IExpectationSetters;
019: import org.easymock.IMocksControl;
020: import org.testng.Assert;
021: import org.testng.annotations.AfterMethod;
022:
023: /**
024: * Manages a set of EasyMock mock objects. Used as a base class for test cases.
025: * <p>
026: * Extends from {@link org.testng.Assert} to bring in all the public static assert methods without
027: * requiring extra imports.
028: * <p>
029: * Provides a common mock factory method, {@link #newMock(Class)}. A single <em>standard</em>
030: * mock control is used for all mock objects. Standard mocks do not care about the exact order in
031: * which methods are invoked, though they are as rigourous as strict mocks when checking that
032: * parameters are the correct values.
033: * <p>
034: * This base class is created with the intention of use within a TestNG test suite; if using JUnit,
035: * you can get the same functionality using {@link MockTester}.
036: * <p>
037: * This class is thread safe (it uses a thread local to store the mock control). In theory, this
038: * should allow TestNG to execute tests in parallel. Unfortunately, as of this writing (TestNG 5.1
039: * and maven-surefire 2.8-SNAPSHOT) parallel execution does not always work fully and consistently,
040: * some tests are dropped, and so Tapestry does not make use of TestNG parallel execution.
041: *
042: * @see EasyMock#createControl()
043: * @see MockTester
044: */
045: public class TestBase extends Assert {
046: private static class ThreadLocalControl extends
047: ThreadLocal<IMocksControl> {
048: @Override
049: protected IMocksControl initialValue() {
050: return EasyMock.createControl();
051: }
052: }
053:
054: private final MockTester _tester = new MockTester();
055:
056: /**
057: * Returns the {@link IMocksControl} for this thread.
058: */
059: protected final IMocksControl getMocksControl() {
060: return _tester.getMocksControl();
061: }
062:
063: /**
064: * Discards any mock objects created during the test.
065: */
066: @AfterMethod(alwaysRun=true)
067: public final void discardMockControl() {
068: _tester.cleanup();
069: }
070:
071: /**
072: * Creates a new mock object of the indicated type. The shared mock control does <strong>not</strong>
073: * check order, but does fail on any unexpected method invocations.
074: *
075: * @param <T>
076: * the type of the mock object
077: * @param mockClass
078: * the class to mock
079: * @return the mock object, ready for training
080: */
081: protected final <T> T newMock(Class<T> mockClass) {
082: return _tester.newMock(mockClass);
083: }
084:
085: /**
086: * Switches each mock object created by {@link #newMock(Class)} into replay mode (out of the
087: * initial training mode).
088: */
089: protected final void replay() {
090: _tester.replay();
091: }
092:
093: /**
094: * Verifies that all trained methods have been invoked on all mock objects (created by
095: * {@link #newMock(Class)}, then switches each mock object back to training mode.
096: */
097: protected final void verify() {
098: _tester.verify();
099: }
100:
101: /**
102: * Convienience for {@link EasyMock#expectLastCall()} with
103: * {@link IExpectationSetters#andThrow(Throwable)}.
104: *
105: * @param throwable
106: * the exception to be thrown by the most recent method call on any mock
107: */
108: protected final void setThrowable(Throwable throwable) {
109: EasyMock.expectLastCall().andThrow(throwable);
110: }
111:
112: /**
113: * Invoked from code that should not be reachable. For example, place a call to unreachable()
114: * after invoking a method that is expected to throw an exception.
115: */
116:
117: protected final void unreachable() {
118: fail("This code should not be reachable.");
119: }
120:
121: /**
122: * Convienience for {@link EasyMock#expect(Object)}.
123: *
124: * @param <T>
125: * @param value
126: * @return expectation setter, for setting return value, etc.
127: */
128: @SuppressWarnings("unchecked")
129: protected final <T> IExpectationSetters<T> expect(T value) {
130: return EasyMock.expect(value);
131: }
132:
133: /**
134: * Asserts that the message property of the throwable contains each of the provided substrings.
135: *
136: * @param t
137: * throwable to check
138: * @param substrings
139: * some number of expected substrings
140: */
141: protected final void assertMessageContains(Throwable t,
142: String... substrings) {
143: String message = t.getMessage();
144:
145: for (String substring : substrings)
146: assertTrue(message.contains(substring));
147: }
148: }
|