Kohei Nozaki's blog 

Comparison of 2 ways of integration testing: Arquillian and Remote EJB


Posted on Tuesday Mar 04, 2014 at 06:51AM in Technology


Arquillian

Pros

  • It enables us to testing of all kind of beans or methods.
    • CDI Managed Beans
    • EJBs that have only no interface view or local interface
    • Methods what returns/receives object which not serializable
    • everything
  • There are many various ways of manipulating testing package.
    • e.g. adding data source definition or persistence descriptor (persistence.xml) for testing purpose is easy because of useful ShrinkWrap.
  • We can keep the package for testing deployment smaller.
    • We can create smaller deployment package which contains only necessary resources for each test case.

Cons

  • It needs deployment for each test execution.
    • It brings longer deployment time for some cases. if you can keep test packages smaller or you can use faster embedded containers, you might think that it's not problem at all.
    • When I want to execute all of test classes, It will execute deployment many times (same as numbers of test classes). I guess it's inefficient.
    • Also there are some ways to avoid it such as creating delegate test classes, but I think it's annoying.
  • It takes some times for making test package.
    • It gives us great ability to manipulate test package with ShrinkWrap, but it takes some time for making test package. it needs to make WAR or EAR through scanning all necessary classes and dependencies (jar files), for each test execution.
  • Dependency resolving is annoying.
    • We can manipulate what testing package contains completely with Arquillian, but I guess it's annoying for some cases.
    • I have tried to resolve dependencies through Arquillian's Maven Plug-in API, but sometimes I got unexpected result which different with standalone Maven (such as exclusion, etc), and resolving is need to be executed for each test execution.
  • We have to include testing dependencies such as Mockito or DBUnit on the deployment.
    • I know it's not a problem for many cases, I just feel it is not likely to me. I guess that these are not required on the server-side.

Remote EJB

Pros

  • We can control the time of deployment completely.
    • We can execute many test classes for deployment only once.
    • It reduces many deployment time and test execution time for some cases.
  • We can do testing against pure production resources.
  • We don't need to another preparation of testing packages through resolving resources and dependencies.
  • It depends on only more simply and standardized technologies.
    • We don't need to mark @RunWith(Arquillian.class) on test classes.
    • All we need is just lookup the remote bean on the method marked @Before, and invoke target method.

Cons

  • Testable resources are limited on EJBs that have remote interface.
    • We can't test CDI Managed Beans on this way.
  • All of method parameters and return object are need to be serializable.
    • Also larger serializable objects in the test would make testing performance worse.
  • We have to create remote interfaces for beans that needs to be tested.
    • It's annoying, and remote interfaces are unnecessary for production environment at some occasions.
  • EJBs are considered as heavier than CDI Managed Beans.
  • Performance of remote EJB lookups may vary between environments.
    • I experienced that it takes 1 second or more with GlassFish3.
    • Now I'm using WildFly 8.0.0Final, it takes only some milli-seconds.
  • We have to deploy the whole application package for every testing.
    • Larger application needs more time for deployment.
    • So, we have to keep the size of projects at appropriate size.

Conclusion and how to overcome cons

  • I prefer Remote EJB at present time.
  • Annoying preparation of remote interfaces are not pain as much to me.
    • we can make remote interfaces this way, it needs only small amount of additional code:
public interface BusinessDayUtil {

    boolean isBusinessDay(Date date);

    Date addDays(Date date, int days);

    @javax.ejb.Remote
    interface Remote extends BusinessDayUtil {
    }

    @javax.ejb.Local
    interface Local extends BusinessDayUtil {
    }
}
  • Implementation class:
@Stateless
public class BusinessDayUtilImpl implements BusinessDayUtil.Local, BusinessDayUtil.Remote {
...
  • And we can inject the bean through local-view easily:
public class MyJobOperatorImpl implements JobOperator {

    @Inject
    BusinessDayUtil.Local businessDayUtil;
...
  • We don't want to EJBs to wrapping Exceptions with EJBException at some occasions.
    • It can avoid on application classes with annotate @ApplicationException
    • Also can achieve on API classes through placement of ejb-jar.xml.
    • I know it's a sidetracking topic, but I wrote for just a note for me.
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee" version="3.1"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd">
    <assembly-descriptor>
        <application-exception>
            <exception-class>javax.persistence.NoResultException</exception-class>
            <rollback>true</rollback>
        </application-exception>
    </assembly-descriptor>
</ejb-jar>
  • Making all of arguments and return object serializable is impossible at some occasions.
    • Such as use of InputStream or OutputStream
    • But I guess we can take the old way which stick with plain JUnit testing with mocking frameworks, at such occasions.
CAUTION: invoking EJBs via local interface will call by reference but invoking via remote interface will call by value. you will get serious problems that different behavior between invoking local and remote interfaces. consider keep using remote interface on production (with accepting some performance degradation) or using modern testing framework such as Arquillian if necessary.



No one has commented yet.

Leave a Comment

HTML Syntax: NOT allowed