Tuesday, May 24, 2011

a TDD framework for EJB3

In Container Test Driven Development for EJB3

Want to write code TDD style but using JEE? Well now you can!

The blog post I did many months ago has now found its way into a useful tool (hopefully).

Background
As most time I write code in Spring or JEE5 environments I have had the opportunity to become partially spoiled by the relative ease of testing Spring "wired" code. The only trouble I have had is basically connected to transactions (the test committed unwanted data) or that I need a small variation of the configuration and the easiest way to do this was do create a new copy of the spring-config (config-hell-yuck).

My experience with TDD 
My experience with the TDD "in-container" approach is aprox 4 years and have written about thousand tests of various types. I think I have a decent experience in the subject, but still have a lot to learn.

TDD, the test driven development.
I have during my years as a developer started to classify the way my tests are written into four categories.
  1. Unit Test, a single class with no relations. (Hard to do in real life for "service layered applications" but its the way to start with TDD). This always just works as no related classes are loaded during its test i.e. no In-Container tooling is needed.
  2. Functional Test, the entire application is "started" somehow and all internal code can be executed without exception. (This is how the Spring-JUnit extensions works). This requires some sort of In-Container testing.
  3. Mocking(Partially functioning) Test, The test can be started as a functional test or as a regular unit test but some parts are in need of mocking. I usually do this for third-party dependencies that I can not do In-Container testing of. Not easy in any tool, in Spring a new config must be created for each type of test.
  4. UseCase Test, this test is done to verify the specification. Its a playback of the intended software usage, for these tests to be easy to maintain and keep in control its a good thing to try to minimize the amount to something manageable. Like max 100 or so. The software I personally tried this "test-type" first time had about 60 (for a peace of software that was about 100k line of code). The interesting thing is that the requirements that we created it from had only 15 use case scenarios. According to me each test here hould have a corresponding use case scenario. The tip is to try to code the test in way that its easy to read as a scenario even though its code. 
If I look at my personal experience the functional tests are the once where i easily can test the code i create without hideous overhead or "meaningless" test code. The second most important one is the mocking test, where i try to not execute some part of the code. This is very useful for fixing bugs in legacy systems where parts are just not easy to run In-Container and for excluding a third party software from the test assertions.
Once the software is "done" i start creating the use-case scenario test and make it "really work". This use case tests can be written earlier to understand all parts of the software in creation.

- Unit Tests are used to verify utilities or classes that have no dependencies. Very good as long as they can be used.
- Function/Mocking test is short and concise and have focus on assertions. There are large amounts of these test. 
- The Use case test is complex and large flows are executed, only key elements are asserted. Never assert any business logic details, just big picture flows.

This is what i learned when coding Spring code. And 2 years ago I went back to JEE .... OMG! Its like stepping back to stoneages, TDD wise. The "TDD bug" had already stung me, I could no longer code without testing. It felt dirty and I felt like i did not have control over the software I was suppose to code.

A possible solution?

It's time to announce a working version of the TDD Tooling for EJB3 :)

In an effort to try to create a tool that can support the four different types of tests that are described above a tooling framework was created that makes it easy to test JEE code. At least it seems to work as intended, i need more to use to prove it though :)

I am personally using it for two separate customers with very good results. The framework is adapted for one of them and used as is for the other. I have personally educated the first customers in TDD coding and shown how we can code in a mix of EJB2/3 and Factories with this tool.

See this presentation from the Javaforum in Gothenburg.
This explains how you can perform Functional and Mocking tests.

Introducing TDD tooling for JEE based code. 

Pros
- Loose coupling to your test code, and no coupling to your business code.
- Automated lifecycle handling of underlying Container and DB transactions.
- Possible partial mocking of any EJB3 service (recommend Mockito or manual mocks).
Semi-pro (proven concept)
- Has been in use by two development teams since january 2011 and over 300 tests are executed with this tool for both projects (at this precise moment). 

Cons
- Only supports part of the JEE specification.
@Stateless, @Stateful, @EJB and @PostConstruct are verified all other part are unverified and might work, but not intentionally.
- Not supported by any companies. (So far)

Thats it from me for now, hope that someone start using this and gives some feedback to me soon :)

Maven dependency example:


<dependency>
    <groupid>org.hrodberaht.inject.extension</groupid>
    <artifactid>tdd</artifactid>
    <version>1.0_RC2</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupid>org.mockito</groupid>
    <artifactid>mockito-all</artifactid>
    <version>1.8.5</version>
    <scope>test</scope>
</dependency>



Assemply JAR with same dependencies included as the maven dependencies above.
http://code.google.com/p/injection-extensions/downloads/list



Friday, October 22, 2010

Performing Unit Tests with the @Inject Container as a Runner

As a response to the following post about the "Perfect Integration Test" i would like to give my point of view of what a perfect test with active connection to a database is. Jboss Blogg entry

The following has a big difference to the Arquillian project, it never intends to be able to execute the same testsuites on different container vendors. Its more focused on creating the fastest and simplest possible UnitTest for your EJB code.

But I must admit that a lot of my inspiration to do this came from Arquillian, i just thought they had the wrong focus.

I will explain how its possible to perform a UnitTest where the following rules are enforced.

  1. The services are "wired" for EJB3 (Stateless/Stateful Sessions Beans supported) automatically with a scanning path configuration.
  2. For each test the "container" is automatically reset
  3. For each test the internal database is rolled back
  4. Its possible to register mocking services by overriding existing configuration, to make it easier to vary the test-suite without reconfoguring the entire software with a new "config class".


All these feature's are enabled with the help of the hrodberaht injection container and an extension to it called ejbunit (might be renamed to just junit as i am thinking about adding spring support as well, as it feels easy enough).
Injection Wiki (the 1.2-SNAPSHOT version though is needed, as its in this version that the cloning support is added)

This is done using the followign techniques.

1. The services are "wired" for EJB3 (Stateless/Stateful Sessions Beans supported) automatically.
- All that is needed is a JUnitRunner and a Project Configuration (scanners are supported)

2. For each test the "container" is automatically reset
- The container is resets to its original state before the test is executed. Original is whatever the config found in the class Project Configuration context.

3. For each test the internal database is rolled back at the end
- All calls to close/commit are prevented (silently) and a rollback is executed once the testsuite is over.
- Works as long as the datasource is created by the Project Configuration

4. Its possible to register mocking services by overriding existing configuration, to make it easier to vary the testsuite without reconfoguring the entire software with a new "config class".
- Is done using a utility that can reach the running @Inject Container for the active test. (supports several active test threads if needed)

So how does this look code wise:
The test
@EJBContainerContext(EJBContainerConfigExample.class)
@RunWith(EJBJUnitRunner.class)
public class TestEJB3ServiceContext {

    @EJB
    private EJB3ServiceInterface ejb3ServiceInterface;

    @Test
    public void testEJBWiring(){
        String something = ejb3ServiceInterface.findSomething(12L);
        assertEquals("Something", something);

        String somethingDeep = ejb3ServiceInterface.findSomethingDeep(12L);
        assertEquals("Something Deep", somethingDeep);
    }

    @Test
    public void testEJBResourceInjectionAndUpdate(){
        String something = anInterface.findSomethingDeepWithDataSource(12L);
        assertEquals("The Name", something);
        anInterface.updateSomethingInDataSource(12L, "A new Name");
        something = anInterface.findSomethingDeepWithDataSource(12L);
        assertEquals("A new Name", something);
    }

    @Test
    public void testEJBWiringWithMockito(){

        EJB3InnerServiceInterface anInterface =
            Mockito.mock(EJB3InnerServiceInterface.class);
        Mockito.when(anInterface.findSomething(12L))
            .thenReturn("Something Deep FormMock");
         EJBResourceHandler
             .registerServiceInstance(EJB3InnerServiceInterface.class, anInterface);

        EJB3ServiceInterface serviceInterface =
             EJBResourceHandler.getService(EJB3ServiceInterface.class);
        String something = serviceInterface.findSomething(12L);
        assertEquals("Something", something);
        String somethingDeep = serviceInterface.findSomethingDeep(12L);
        assertEquals("Something Deep FormMock", somethingDeep);
    }
}

So what is all this:
1. The config @EJBContainerContext(EJBContainerConfigExample.class)
- This contains the code that "scans" for all EJB's in the software, using package scanning. This is similar to the annotation @Deployment used by Arquillian.

public class EJBContainerConfigExample extends EJBContainerConfigBase {

    public EJBContainerConfigExample() {
        String dataSourceName = "DataSource";
        addResource(dataSourceName,
             ResourceCreator.createDataSource(dataSourceName));
        addSQLSchemas(dataSourceName,
            "test/org/hrodberaht/inject/extension/ejbunit");
    }

    @Override
    public InjectContainer createContainer() {
        return createAutoScanEJBContainer(
             "test.org.hrodberaht.inject.extension.ejbunit.ejb3.service");
    }


- "addResource" Will register a  datasource for the application named "DataSource", this works as any datasource and can be injected with @Resource as regular with EJB3.
- "addSQLSchemas" Will try to execute all SQL files found in this directory names with "create_schema*" once all those are executed all file with the name "insert_data*" will be executed. This execution results will be commited to the datasource selected in the method call.
-  "createContainer" A container will be created and returned (this is used by the Runner)

2. @RunWith(EJBJUnitRunner.class)
This will take care of all the gritty details with rollback of the active connection and reset of the "container".
Before a testsuite is executed a clone of the container is made and registered as the active container for the running test (after the original has been created from the Configuration).

3. @EJB private EJB3ServiceInterface ejb3ServiceInterface;
All testclasses that have the RunWith can have injected Service (both @EJB and @Inject works)

4. The tests themselves
Are not that special, only that they can be be executed without any before/after handling for rollback or cleanup of the database.
4.1 testEJBWiring
The test for this will only verify that the injection have done what they are suppose to.
4.2 testEJBResourceInjectionAndUpdate
The test will verify that
- the SQL scripts have been executed (first row is a selection of the id 12)
- the Datasource has been injected correctly to the inner service bean
- that the update code works as intended and can be refetched from the running database.

Note: In the real test suite a second test is execute to verify that the update is automatically rolled
back by the testrunner.

All this code can be found in extensions to the hrodberaht @Inject. At the google code projects.
http://code.google.com/p/java-simple-utils/
http://code.google.com/p/injection-extensions/

The code for the test case used as example here can be found at:
http://code.google.com/p/injection-extensions/source/browse/trunk/ejbunit/src/test/java/test/org/hrodberaht/inject/extension/ejbunit/ejb3/TestEJB3ServiceContext.java

A simple example POM file for anyone that want to test this has been committed to the test suite.
http://code.google.com/p/injection-extensions/source/browse/trunk/ejbunit/example-pom/pom.xml
PS: I have not verified the POM on another computer so please report any problems if you try it.

Sunday, September 19, 2010

JSR 330 and @Inject

The background (why the hell create a new IoC DI framework)
First of i would like to explain that the initial intention from my side was to create a very simple InjectionContainer that could extend Spring/Guice when needed and be replaces as soon as Spring/Guice released their version that supports JSR-330.

After waiting and not understanding how and when Spring and Guice was actually going to do this I started to play with the JSR 330 TCK. Once the TCK was implemented with the @Inject IoC I realized that this is quite powerful and that I wanted and needed extensions for it to be useful in a real world application.

The primary reason for this research from my side was to get a deep understanding of IoC DI and to finally implement a generic solution of the many "simplifications" I have always created in a application when I start to develop for a customer.

Basic project info/note
I am a Maven2 addicted developer (its not all good but its worth it in the end), so all projects are Maven'ized and all releases are deployed to central Maven repository (thanks to Sonatype).

Release 1.1.0 of Simple Java (with Config/i18n and Inject implementations bundled)

The Different projects

- Config
Java properties has been the same for ages and are very not very useful. This is an extension to those properties with Generics and override (via System parameters) support.
- i18n
Java Format packages has a lot of features but they are sometimes hard to "find" and use in a good way. This package does that, it gathers the formatters and configures them in a more useful way. And it also fixes an irritating bug that Sun refuses to solve with the wrong blank-space being used as a thousand separator.

- @Inject (the org.hrodberath.inject)
The Injection framework implementation is a certified (not official yet though) version of the JSF 330 specification. The TCK test suite can be found in the code base.

The @Inject framework today implements a small but similar feature set to Guice

Current feature set (in release 1.1.0)
  • support for new and singelton scope
    - also thread and inheritable-thread but these are custom
  • support for javax.inject.Provider (very useful interface)
  • support for configuration of older non @inject friendly factories via the InjectionFactory
  • Has extensive registering support (with "inheritable" modules), this is the intended strong point of this framework.
    - Has scanning support
    - Has module "extends" support (like inheritance)
    - Simple System.out printing of active configuration
Planned additions (in release 1.2.0)
  • support for attaching older non @inject friendly variable factory via a VariableInjectionFactory
  • SPI support for adding custom @Inject and @PostConstruct and @Scope annotations
  • Service Configuration live exporting to XML
  • More and better support for multi module configuration "mixing" where the exact results of these mixes can be seen and understood easily.
    - Implement the @Extends annotation that was added in 1.1
    - Support multiple "extends" (multi inheritance)
    - Support advance configuration where support for standard / customer / custom variations are supported and easy to understand how to configure. Add some way to switch between these config variations.
- Extensions for @Inject (the org.hrodberath.inject.extension)
I have planned the following extensions for release soon.

Ongoing features (Has SNAPSHOT code that is close to working as intended)

Transaction (JDBC and JPA support, not JTA or XA)
  • Uses EJB annotations with AspectJ
  • All transaction types from EJB implemented and supported
  • JPA --> JDBC shared connection support implemented
  • JDBC Helper package included
  • Junit Runner
    - Transacted and Container manager runner implemented
  • TODO: create more test suites for mixed transactions
JSF (@Inject and Transaction supported JSF with no-config setup)
  • JSF Injection Provider for @Inject implemented
  • OpenTransactionInView via a Filter is implemented
  • TODO: no config, need inspiration here: use a Annotation? naming?
Planned features (has no SNAPSHOTS or source code at this moment)

EJB 3.0 JUnit Framework (with Mocking help connected to mockito)
  • Extreme bootstrap speed (less than 1s for a standard project with 100 services or so)
  • @Inject and Transaction support for an EJBJunitRunner built on @Runwith
  • Support for @EJB and @Resource
    • Not entitys, use hypersonic with JPA for this, its loads simpler.
NetBeans RCP
  • @Inject and Transaction support
Eclipse RPC
  • @Inject and Transaction support
GWT (still unsure if this will be supported, as I don't "get it" GWT at this moment)
  • @Inject and Transaction support
Spring

Connect the @Inject container to Spring managed beans to support the usage of any Spring bean inside the container.
  • JMS Bean usage support verified
  • WebFlow beans support verified
  • RMI Bean usage support verified
Example Application for JSF (built on the superb JSF framework PrimeFaces)

This is intended as the showcase to prove that the coding can be done very fast and simple.
Points to sonatypes snapshot repository for the snapshot dependencies.
Usage examples

All projects are syncronized to central Maven and can be used without a extra addition of repository. Snapshots need the sonatype repository though,
https://oss.sonatype.org/content/repositories/snapshots/

See http://code.google.com/p/java-simple-utils/

Simple Java Config


public class AnyApplicationConfig extends ConfigBase {
private static final String DEFAULT_CONFIG = "classpath:/basicConfig.properties";

public static void initConfig() throws ParseException {
    initConfig(DEFAULT_CONFIG);
}
public static void initConfig(String resource) throws ParseException {
    String externalConfig = System.getProperty("config.externalfile");
    if(!StringUtil.isBlank(externalConfig)){
        // This initilized (reads) the config
        new AnyApplicationConfig(resource, externalConfig);
    }else{
        // This initilized (reads) the config
        new AnyApplicationConfig(resource, null);
    }
}

public interface ApplicationState {
    ConfigItem<String> A_STRING = new ConfigItem<String>(String.class, "anyapp.astring");
    ConfigItem<Date> A_DATE = new ConfigItem<Date>(Date.class, "anyapp.adate");
    ConfigItem<Integer> A_INTEGER = new ConfigItem<Integer>(Integer.class, "anyapp.ainteger");
    ConfigItem<Long> A_LONG = new ConfigItem<Long>(Long.class, "anyapp.along");
}


Simple Java i18n
Wiki Guide: http://code.google.com/p/java-simple-utils/wiki/i18n

// This mimics what can be done in a software using the profile provider.
Locale testProviderLocale = new Locale("en", "US");
LocaleProvider.setThreadLocaleProvider();
// This mimics what can be done in a RequestFilter for example
LocaleProvider.setProfile(new LocaleProfile(testProviderLocale));
// All calls to the provider from now on in the current thread will return this locale
LocaleProvider.getProfile().getLocale();

// The following code would now follow this locale
String testDate = "2010-01-01";
Formatter<Date> formatter = Formatter.getFormatter(Date.class);
Date aDate = formatter.convertToObject(testDate);
String aStringDate = formatter.convertToString(aDate);


Simple Java Injection (@Inject)
Wiki Guide: http://code.google.com/p/java-simple-utils/wiki/Injection
JSR 330 Annotation supported Container Configuration example:

InjectionRegisterJava registerJava = new InjectionRegisterJava();
registerJava.register(new RegistrationModuleSimple() {
    public void registrations() {
        register(AnyService.class).annotated(DoNothing.class)
            .scopeAs(ScopeContainer.Scope.SINGLETON)
            .with(AnyServiceDoNothingImpl.class);
        register(AnyService.class)
            .registeredAs(SimpleInjection.RegisterType.FINAL)
            .with(AnyServiceDoSomethingImpl.class);
    }
});

JSF and JUnit example setup with Injection support

@InjectionContainerContext(ModuleContainerForTests.class)
@RunWith(InjectionJUnitTestRunner.class)
@TransactionAttribute
public class TestJPATransactionManager {

    @Inject
    private TransactedApplication application;
...
}



The details about this code is
1. @InjectionContainerContext
- This is the InjectionContainer JUnitRunner Container Context
2. @RunWith
- This is the JUnit annotation that connects the Container to JUnit and adds transaction support when needed.
3. @TransactionAttribute
- This is the EJB3 annotation and it activates transaction support for all tests in this class. InjectionJUnitTestRunner is the class that actually does this.

A JSF Bean with Injected services

@ManagedBean(name = "personBean")
@RequestScoped
public class WebInjectBean {

    @Inject
    private ServiceInject serviceInject;
}


Config in web.xml for this to work
<context-param>
<param-name>com.sun.faces.injectionProvider</param-name>
<param-value>org.hrodberaht.webexample.web.ApplicationJSFResolverImpl</param-value>
</context-param>


A very simple example Application with the Injected transaction manager for a JPA configured application.
See the Google Code link

public class JPATransactedApplication implements TransactedApplication {

    @Inject
    private Provider<EntityManager>

    @TransactionAttribute
    public void createPerson(Person person) {      
        EntityManager em = entityManager.get();
        em.persist(person);
    }
}


The Application with the Injected transaction manager for a JDBC configured application.
See the Google Code link

public class JDBCHelperApplication {

    @Inject
    private JDBCService jdbcService;
  
    public void createAdvancedModel(AdvanceModel advanceModel) {
    Insert insert = jdbcService.createInsert("advanceModel");
        insert.field("id", advanceModel.getId());
        updateAllFields(advanceModel, insert);
        jdbcService.insert(insert);
    }

    public AdvanceModel findAdvancedModel(Long id) {
        String sql = "select * from AdvanceModel where id = ?";
        return jdbcService.querySingle(sql, new AdvanceModelIterator(), id);
    }
    ...
}


Example configuration from the proof of concept project
See Google Code link

InjectionRegisterScan registerJava = new InjectionRegisterScan();
registerJava.registerBasePackageScan("org.hrodberaht.webexample.service.impl");

InjectionRegisterModule register = new InjectionRegisterModule(registerJava);
final TransactionManager transactionManager =
new TransactionManagerJPAImpl(Persistence.createEntityManagerFactory("web-example-jpa"));
register.register(new TransactionManagerModule(transactionManager, register));