001: package org.mockejb.test.entity;
002:
003: import java.util.Collection;
004: import javax.naming.*;
005:
006: import junit.framework.TestCase;
007: import org.easymock.MockControl;
008:
009: import org.mockejb.*;
010: import org.mockejb.interceptor.*;
011: import org.mockejb.jndi.*;
012:
013: /**
014: * Demonstrates BMP Entity bean support.
015: * MockEJB calls BMP entity beans same way with session beans,
016: * however finders have to be handled using aspects/interceptors framework.
017: * BMP finders always return primary key(s), so clients have to write
018: * interceptors to translate primary key to the entity.
019: */
020: public class BMPEntityBeanTest extends TestCase {
021:
022: // JNDI context and MockContainer instance used by all tests in this class
023: private MockContainer mockContainer;
024: private Context context;
025: private AspectSystem aspectSystem;
026:
027: // We use PersonHome in all tests
028: private PersonHome personHome;
029:
030: public BMPEntityBeanTest(String testName) {
031: super (testName);
032: }
033:
034: /**
035: * Sets up our mock container, JNDI context and deploy the beans that we need.
036: */
037: public void setUp() throws Exception {
038:
039: // we use aspects in most of the tests here
040: aspectSystem = AspectSystemFactory.getAspectSystem();
041:
042: // MockContextFactory becomes the primary JNDI provider
043: MockContextFactory.setAsInitial();
044: context = new InitialContext();
045:
046: // Creating MockContainer deletes all aspects from AspectSystem and clears EntityDatabase
047: mockContainer = new MockContainer(context);
048:
049: // Deploy the person bean
050: EntityBeanDescriptor personDescriptor = new EntityBeanDescriptor(
051: Person.JNDI_NAME, PersonHome.class, Person.class,
052: PersonBMPBean.class);
053:
054: mockContainer.deploy(personDescriptor);
055:
056: // Obtain personHome for use in the tests
057: personHome = (PersonHome) context.lookup(Person.JNDI_NAME);
058:
059: }
060:
061: public void tearDown() {
062: // cleanup JNDI settings
063: MockContextFactory.revertSetAsInitial();
064: }
065:
066: /**
067: * Demonstrates how to setup BMP finder support with the help of
068: * interceptors. PersonFinderAspect (see the code at bottom of this file)
069: * ignores the PK values returned by the real finder and substitutes them
070: * with the Person entities that it creates.
071: * This can be used to provide mock data for testing as opposed to
072: * relying on the database.
073: */
074: public void testFinderUsingAspect() throws Exception {
075: // add aspect that handles finders
076: aspectSystem.add(new PersonFinderAspect());
077:
078: Person person = personHome.findByName("John", "Doe");
079: assertNotNull(person);
080: assertEquals("Doe", person.getLastName());
081: }
082:
083: /**
084: * Demonstrates how to tell MockEJB to resolve the PKs returned by the
085: * finder without the use of interceptors.
086: */
087: public void testFinderUsingEntityDatabase() throws Exception {
088: // Create mock entity
089: MockControl personBeanControl = MockControl
090: .createControl(Person.class);
091: Person createdPerson = (Person) personBeanControl.getMock();
092:
093: createdPerson.getId();
094: personBeanControl.setReturnValue(1L);
095: createdPerson.getFirstName();
096: personBeanControl.setReturnValue("John");
097: createdPerson.getLastName();
098: personBeanControl.setReturnValue("Doe");
099:
100: personBeanControl.replay();
101:
102: /* Add mock entity to the "database" so MockEJB could resolve the PKs returned by the finder.
103: * For BMP, MockEJB searches the EntityDatabase for every PK returned by the finder.
104: */
105: mockContainer.getEntityDatabase().add(PersonHome.class,
106: new Long(1), createdPerson);
107: PersonHome personHome = (PersonHome) context
108: .lookup(Person.JNDI_NAME);
109: Person foundPerson = personHome.findByName("John", "Doe");
110: assertEquals(createdPerson, foundPerson);
111:
112: // Test the finder which returns the collection
113: Collection people = personHome.findByFirstName("John");
114: assertTrue(people.size() > 0);
115: foundPerson = (Person) people.iterator().next();
116: assertEquals(createdPerson, foundPerson);
117:
118: }
119:
120: /**
121: * This test demonstrates how we can test BMP entities that
122: * indeed read something from the database.
123: * MockEJB does the following:
124: * it calls the finder, checks if the returned PK is in the EntityDatabase.
125: * If not, it creates a new entity instance and calls ejbLoad on it
126: */
127: public void testFinderAndEjbLoad() throws Exception {
128:
129: PersonHome personHome = (PersonHome) context
130: .lookup(Person.JNDI_NAME);
131:
132: /* BMPPersonBean finder always returns 1, so we're relying on this.
133: * We'll also rely on ejbLoad to populate the entity.
134: * BMPPersonBean.ejbLoad does not go to the database,
135: * it only sets the PK so we'll check that.
136: */
137: Person foundPerson = personHome.findByName("John", "Doe");
138: // did the ejbLoad work?
139: assertEquals(1L, foundPerson.getId());
140:
141: // Test the finder which returns the collection
142: Collection people = personHome.findByFirstName("John");
143: assertTrue(people.size() > 0);
144: foundPerson = (Person) people.iterator().next();
145: assertEquals(1L, foundPerson.getId());
146: }
147:
148: // *** Interceptors used by this test case
149:
150: /**
151: * Handles findByName calls
152: */
153: class PersonFinderAspect implements Aspect {
154:
155: /**
156: * Intercept findByName method.
157: */
158: public Pointcut getPointcut() {
159: // Note that we are intecepting target method on the bean
160: // as opposed to the interface method. Unlike in CMP case, we can do it
161: // because BMP entities have defined finder methods.
162: return new MethodPatternPointcut(
163: "PersonBMPBean\\.ejbFindByName");
164: }
165:
166: public void intercept(InvocationContext invocationContext)
167: throws Exception {
168: Object[] paramVals = invocationContext.getParamVals();
169:
170: // now create
171: invocationContext.setReturnObject(create(
172: (String) paramVals[0], (String) paramVals[1]));
173: // We don't need to proceed to the next interceptor since we're done with the finder
174: }
175:
176: /**
177: * Creates Person entity using "genericCreate" method which creates an
178: * instance of an entity without calling the actual "ejbCreate"
179: */
180: private Person create(String firstName, String lastName)
181: throws Exception {
182:
183: Context context = new InitialContext();
184: GenericHome home = (GenericHome) context
185: .lookup(Person.JNDI_NAME);
186:
187: Person person = (Person) home.genericCreate();
188: person.setFirstName(firstName);
189: person.setLastName(lastName);
190:
191: return person;
192: }
193:
194: }
195:
196: }
|