Adam Bien's Weblog

Friday Jun 26, 2009

Unit Testing EJB 3.1 ...When 0.8 Seconds Are Too Long [SOURCE CODE INCLUDED]

EJB 3 are just POJOs, so there is no need to unit-test them inside the EJB container. You could just instantiate them in the unit test. Sometimes it is needed to change a behavior of a session bean, to cause an exception or test the boundary in another: 


@Stateless
public class ServiceFacade {
    @EJB
    Service service;

    public boolean isOne(){
        int nr = service.getNumber();
        return (nr == 1);
    }
}

I would like to test, whether the ServiceFacade returns "false" in case the number is not 1.
The problem:

@Stateless
public class Service {

    public int getNumber(){
        return 1;
    }
}

...its hardcoded.... Mockito is just perfect for testing such cases.

import com.abien.business.nointerface.control.Service;
import org.junit.Test;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;

public class ServiceFacadeTest {

    @Test
    public void twoIsFalse(){
        Service service = mock(Service.class);
        when(service.getNumber()).thenReturn(2);
        ServiceFacade facade = new ServiceFacade();
        facade.service = service;
        assertFalse(facade.isOne());
    }
}

You can easily change the return value of every (non-final) class for test purposes. The whole project, with mockito libraries, was pushed into http://kenai.com/projects/javaee-patterns (tested with Netbeans 6.7rc3 and Glassfish v3 Preview).

The whole test is executed in 0.2 seconds on my machine. Four times faster than 0.8 :-). Btw. Glassfish v3 (with EJB 3.1 container) starts in about 5-10 seconds - the whole application is deployed in about 2 seconds...

[In the Real World Patterns - Rethinking Best Practices book several unit-testing strategies are discussed - but not mockito. It will change in the Iteration Two] 


[my tweets]  Rss My book: Real World Java EE - Rethinking Best Practices

Kommentare:

geee, public property!

i'm using EasyGloss for this. This thing can inject evrything i need. For mocking i'm using EasyMock...

@Before
...
private JavaEEGloss gloss = new JavaEEGloss();

DateUtilLocal dateUtilBean = EasyMock.createMock(DateUtilLocal.class);
gloss.addEJB(dateUtilBean);

SummaryReportLocal summaryReportBean = gloss.make(SummaryReportBean.class);

@Test
...
expect(dateUtilBean.getDate()).andReturn(new Date());
replay(dateUtilBean);
summaryReportBean.aggregate();
verify(dateUtilBean);
[/code]

Gesendet von temonix am June 26, 2009 at 09:54 AM CEST #

@Temonix

its not public, but package visibility. But seriously - why not? What can happen in worst case?

Thank you for the EasyMock sample!,

regards,

adam

Gesendet von Adam Bien am June 26, 2009 at 10:17 AM CEST #

> What can happen in worst case?
There will break the encapsulation. User ServiceFacade shouldn't know that inside there is a variable service. Using private statement prevents the possibility that not experienced developer wants to have access to the service directly

Gesendet von temonix am June 26, 2009 at 02:08 PM CEST #

@Temonix,

>not experienced developer wants to have access to the service directly

did you ever encounter such a problem in practice? In EJB 3.0 it cannot happen, because of mandatory business interfaces. But you are right - it's potentially possible in EJB 3.1.

Gesendet von Adam Bien am June 26, 2009 at 04:26 PM CEST #

Senden Sie einen Kommentar:
  • HTML Syntax: Ausgeschaltet
Interviews/About
My Recent Book
Java One 2009
CommunityOne East N.Y.C
JavaONE 2008 Interview
Search
...the last 150 posts
...the last 10 comments
greenfire.dev.java.net
Links
my.netbeans.org
Visitors
License