Archive

Archive for June, 2010

Using Embedded JBoss for functional flow testing for EJB3

June 21st, 2010 Shrihari No comments

From the past few days, I have been trying to evaluate various mechanisms to acheive functional flow testing for a runtime EAR deployable. Under the assumption that the final deployment will be on JBOSS-AS-5.1.x, our goal is to chalk out a testing environment thats close to the actual deployed environment.

Various mechanisms for setting up the environment surfaced.

  • Deploying EAR using Maven-Cargo-Plugin (jboss51x) including options to start jboss (pre-integration-test) and stop jboss(post-integration-test) and perform integration tests.
  • Using Embedded JBOSS to start/stop the container pre/post test-case execution and deploy the EAR.
  • Using OpenEJB, an embeddable and lightweight EJB 3.0 Implementation container environment.
  • Using Arquillian(framework to perform integration test) and Shrinkwrap(framework to create JAR/WAR/EAR archive dynamically) APIs from JBOSS

In this edition of the write-up, I would like to focus on the preparing a deployable for Embedded JBOSS, for an example flow. Lets consider
a naive shopping cart example which would given a list of items (with valid item codes), would persist the cart details, generate an invoice
amount. Following are the stateless bean interface and implementation in EJB3 semantics:

package shoppingcart;
import javax.ejb.Local;

@Local
public interface ShoppingCart
{   public Double generateInvoice(List items,String coupon) throws InvalidCartException;
}

Assuming isCouponValid() and getDiscount()/addTax are functional stubs implemented appropriately, following is the bean code.

package shoppingcart;
import javax.ejb.Stateless;
import javax.jpa.PersistenceContext;

@Stateless
public class ShoppingCartBean implements ShoppingCart
{   @PersistenceContext EntityManager em;

public Double generateInvoice(List items,String coupon) throws InvalidCartException
{  if(items.size() <= 0)
throw new InvalidCartException("No items present in the shopping cart!");
if(isCouponValid(coupon))
throw new InvalidCartException("Shopping cart's Coupon Code is not valid!");
Double totalPrice = 0;
for(Item item:items)
{   totalPrice += (item.getQuantity()*item.getPrice()));
}
totalPrice -= getDiscount(coupon);
totalPrice += addTax(totalPrice);
return totalPrice;
}
}

Use the Maven configuration for Embedded JBoss, we could set up the necessary environment for implementing the test cases. Following are the additional changes:
1) If you have a datasource file, copy it under test/resources/deploy.
2) Copy persistence.xml under test/resources/META-INF.

Once done. here is the JUnit code to test the functional flow for shopping cart

package shoppingcarttest;

import org.jboss.bootstrap.spi.Bootstrap;
import org.jboss.deployers.spi.DeploymentException;
//other imports..

public class ShoppingCartTest
{  @BeforeClass
public static void startup() {
try {
if (!Bootstrap.getInstance().isStarted()) {
Bootstrap.getInstance().bootstrap();
}
deploy();
} catch (DeploymentException deploy) {
deploy.printStackTrace();
}
}

private static void deploy() {
Bootstrap bootstrap = Bootstrap.getInstance();
try
{    bootstrap.deployResourceBase(ShoppingCart.class);
bootstrap.deployResourceBases("META-INF/persistence.xml");
} catch (DeploymentException e)
{    throw new RuntimeException("Unable to deploy", e);
}
}

@Test
public void testShoppingCart()
{   InitialContext ctxt = new InitialContext();
ShoppingCart cart = (ShoppingCart)ctxt.lookup("ShoppingCartBean/local");
List items = new ArrayList(2);
items.add(new Item("Nokia E61",1));
items.add(new Item("Nokia E61 cable",1));
Double totalPrice = cart.generateInvoice(items, "XYZ123");
assertTrue(totalPrice > 0);
}

}

Using JBoss’s Bootstrap SPI, one can start the embedded container and deploy the EAR containing the enterprise-bean-under-test. We can also embrace TDD/BDD approach using mocks, er. Mockito

Understanding Exception Handling on Mock objects

June 6th, 2010 Shrihari No comments

Mockito is the recommended and used mocking testing framework which provides varied function points to mock and verify interactions. It provides a parallel support to TestNG or JUnit for faster Test Driven Development (TDD) adoption in newer teams. In this edition of the write-up I would explore the concept of mocking with exception handling.

Lets consider a user credential validation login, before user getting authenticated into the system. If the credential validation fails, the system is expected to throw an application exception. However if it passes, the actual authentication to the system should
happen. With the familiarity with TestNG and Mockito, lets look the test case code

@Test(expectedException=UserValidationException.class)
public void testCredentialsValidation()
{  //create a mock to return false for validation - to fail login
UserCredentials credentials = mock(UserCredentials.class);
when(credentials.validate(anyString(),anyString())).thenReturn(false);

//Call the login service to gain entry
LoginService service = new LoginService(credentials);
service.loginuser("sample","sampl3");
}

Please note here that UserCredentials is only being mocked here, not the LoginService. The reason is to run the induced behaviour of the mocked UserCredentials on the actual LoginService functionality. A mocked object will behaviour only according to what has been induced.

Having looked at the test code, lets look at the actual logic implementation

public interface UserCredentials
{  public boolean validate(String username,String passwordtext);
}
public class LoginService
{  private UserCredentials credentials;

public LoginService(UserCredentials credentials)
{ this.credentials = credentials;
}

public void loginuser(String user, String passwd) throws UserValidationException
{   if(!credentials.validate(user,passwd))
throw new UserValidationException("Username or password invalid..");
//actual authentication process...
}
}
public UserValidationException extends RuntimeException
{  private String message;

public UserValidationException(String msg)
{   message = msg;
}
}

UserValidationException extends RuntimeException for brevity purposes, so that the test code signature is not affected. There is another methodology whereby we could induce behaviour of throwing an exception on the mocked object, even though the actual need not throw any exception.

doThrow(new UserValidation()).when(loginservice).loginuser(anyString(),anyString());

Unfortunately this is at the method level and not at the individual statement level. Am looking at options on mocking exceptions at the method  statement level for the mocked objects. Any thoughts!

Categories: jee-light Tags: ,