I’m trying to get to grips with EJB3Unit, to unit test an EJB 3.1 stateless bean, but EJB3Unit complains because my EJB does not have a “business interface”. But I thought all this “business interface” stuff was a relic of EJB 2, so I should not need it. Is this because I’m using EJB3Unit incorrectly? What do I have to do to get EJB3Unit to work for my unit test?
My EJB is essentially this:
package uk.co.nildram.badamson.aoc4;
@Stateless
@LocalBean
public class AocService {
@PersistenceContext(unitName = "aoc4")
private EntityManager entityManager;
// Other code
}
My unit test class is essentially this:
package uk.co.nildram.badamson.aoc4;
public final class AocServiceTest extends BaseSessionBeanFixture<AocService> {
private static final Class<?>[] USED_ENTITY_BEANS = {};
public AocServiceTest() {
super(AocService.class, USED_ENTITY_BEANS);
}
@Test
public void testCreateSessionBean() {
final AocService bean = getBeanToTest();
checkInvariants(bean);
}
public static void checkInvariants(final AocService service) {
// assertions
}
// Other code
}
The unit tests fail because of the following exception:
java.lang.IllegalStateException: No business interface found on class 'uk/co/nildram/badamson/aoc4/AocService'.
at com.bm.ejb3metadata.annotations.helper.bean.session.SessionBusinessInterfaceFinder.resolve(SessionBusinessInterfaceFinder.java:86)
at com.bm.ejb3metadata.annotations.helper.bean.SessionBeanHelper.resolve(SessionBeanHelper.java:69)
at com.bm.ejb3metadata.annotations.helper.ResolverHelper.resolve(ResolverHelper.java:91)
at com.bm.ejb3metadata.MetadataAnalyzer.analyze(MetadataAnalyzer.java:82)
at com.bm.ejb3metadata.MetadataAnalyzer.analyzeClasses(MetadataAnalyzer.java:49)
at com.bm.ejb3metadata.MetadataAnalyzer.initialize(MetadataAnalyzer.java:36)
at com.bm.ejb3metadata.annotations.metadata.MetaDataCache.getMetaData(MetaDataCache.java:129)
at com.bm.ejb3metadata.annotations.metadata.MetaDataCache.getDynamicModuleCreator(MetaDataCache.java:105)
at com.bm.creators.SessionBeanFactory.getInjector(SessionBeanFactory.java:78)
at com.bm.creators.SessionBeanFactory.createSessionBean(SessionBeanFactory.java:60)
at com.bm.testsuite.BaseSessionBeanFixture.setUp(BaseSessionBeanFixture.java:92)
at junit.framework.TestCase.runBare(TestCase.java:132)
at junit.framework.TestResult$1.protect(TestResult.java:110)
at junit.framework.TestResult.runProtected(TestResult.java:128)
at junit.framework.TestResult.run(TestResult.java:113)
at junit.framework.TestCase.run(TestCase.java:124)
at junit.framework.TestSuite.runTest(TestSuite.java:243)
at junit.framework.TestSuite.run(TestSuite.java:238)
at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:83)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
The code throwing the exception seems to be http://ejb3unit.sourceforge.net/xref/com/bm/ejb3metadata/annotations/helper/bean/session/SessionBusinessInterfaceFinder.html. That indeed seems to be demanding a “javax/ejb” interface. But I have a @LocalBean, so my class should not require any interfaces.
Remote and local business interface are part of EJB 3.x (introduced in EJB 3.0), not relic from EJB 2.x. What you are referencing as relic is maybe EJB 2.x remote and local home interfaces – those ones that forced to extend javax.ejb.EJBHome/EJBLocalHome and forced to provide create-methods.
You use concept of no-interface view (no separate business interfaces) which is part of EJB 3.1 and EJB3Unit supports only EJB 3.0 and that’s why it doesn’t work. You need interface that is annoted with @Local or @Remote and make AocService to implement it and then use AocService via it’s interface.
EJB 3.1 specification uses following terminology:
Example with EJB 3.x remote business interface, local business interface
and no-interface view: