Here is a sample Java code of a typical EJB client. Any Java developer who has ever written code to call EJBs will be well aware of following Java code snippet.
import javax.naming.InitialContext;
import javax.naming.Context ;
import com.sales.Product.*;public void TestPrice() {
try
{
// create and load properties
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
props.put(Context.PROVIDER_URL, "t3://localhost:7001");
// get initial context using loaded properties
InitialContext context = new InitialContext(props);
// JNDI lookup
Object jndi = context.lookup("ProductHome");
// narrow down remote object to get remote home
ProductHome home = (ProductHome) javax.rmi.PortableRemoteObject.narrow(jndi,
ProductHome.class);
// create service from remote home
ProductService productService = home.create();
// check if Product IDs exist in Database
boolean result1 = productService.isValid(1801);
boolean result1 = productService.isValid(9999);
// assert our results
assertEquals( result1, true );
assertEquals( result2, false );
}
catch (Exception ex)
{
ex.printStactTrace();
}
}
This code is first trying to do a lookup for JNDI object “ProductHome” (remote home) deployed on a Weblogic application server. Upon a successful lookup it creates a service object from remote home and finally calls isValid(int) method on the service class.
Now let’s see how are we going to implement this code in a FitNesse test table using Generic Fixture.
!path weblogic.jar !path productEjbs.jar '''Set debug ON for Generic Fixture''' !| Generic Fixture | Generic Fixture | | set debug | true |'''Load the required properties''' !| Generic Fixture | props=java.util.Properties | | put | javax.naming.Context.INITIAL_CONTEXT_FACTORY | weblogic.jndi.WLInitialContextFactory | | put | javax.naming.Context.PROVIDER_URL | t3://localhost:7001 | | toString | | '''Load the Remote Home class''' !| Generic Fixture | java.lang.Class | | homeClass=forName | com.sales.Product.ProductHome | '''Lookup JNDI from Initial Context''' !| Generic Fixture | javax.naming.InitialContext | props= | | jndi=lookup | ProductHome | | obj=javax.rmi.PortableRemoteObject.narrow | jndi= | homeClass= | '''Cast Narrowed object to Remote Home object''' !| Generic Fixture | homeClass= | | homeObj=cast | obj= | '''Create service object from remote home object''' !| Generic Fixture | homeObj= | | service=create | '''Check if given Product IDs exist in Database''' !| Generic Fixture | service= | | isValid | 1801 | | true | | isValid | 7000 | | false |
Since we had to operate on multiple objects and classes, we have heavily used the variables feature of Generic Fixture. Most of the test code is self explanatory with the comments provided on top of each table. Only tricky thing is to call Class.Cast(Object) method to get the casting right for ProductHome home = (ProductHome) javax.rmi.PortableRemoteObject.narrow(jndi, ProductHome.class) call in Java code.
Go ahead and give it a try.
So using Generic Fixture we completely eliminated the need to write Java code given in above section to test our ProductHome EJB. Writing EJB test in Generic Fixture of course has huge advantage over writing Java code. These test tables can be altered by any non-developer. For ex: if there is a new requirement to test validity of Product ID: 5319 then it is as simple as adding this line in the last table:
| isValid | 5319 | | true |
Which is much easier than finding a developer to change and re-compile the Java code.
I intentionally chose a simple operation on ProductHome EJB here to pass on the idea but almost any operation on EJBs can be performed using this approach, thus giving us the ability to build really robust and useful acceptance tests without writing any Java code.