Testing an EJB with JUnit

The accepted answer requires mocking a lot of code, including the persistence layer. Use an embedded container to test the actual beans, instead; otherwise, mocking the persistence layer results in code that barely tests anything useful.

Use a session bean with an entity manager that references a persistence unit:

@Stateless
public class CommentService {

    @PersistenceContext(unitName = "pu")
    private EntityManager em;

    public void create(Comment t) {
        em.merge(t);
    }

    public Collection<Comment> getAll() {
        Query q = em.createNamedQuery("Comment.findAll");
        Collection<Comment> entities = q.getResultList();
        return entities;
    }
}

The entity bean:

@Entity
@NamedQueries({@NamedQuery(name = "Comment.findAll", query = "select e from Comment e")})
public class Comment implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }
}

This persistence unit is defined in the persistence.xml file as follows:

<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">

  <persistence-unit name="pu" transaction-type="JTA">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <class>org.glassfish.embedded.tempconverter.Comment</class>
    <properties>
      <property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
    </properties>
  </persistence-unit>
</persistence>

The transaction type must be JTA.

Then write a test that creates and destroys the EJB container (GlassFish embedded container):

public class CommentTest extends TestCase {

     private Context  ctx;
     private EJBContainer ejbContainer;

    @BeforeClass
    public  void setUp() {
        ejbContainer = EJBContainer.createEJBContainer();
        System.out.println("Opening the container" );
        ctx = ejbContainer.getContext();
    }

    @AfterClass
    public  void tearDown() {
        ejbContainer.close();
        System.out.println("Closing the container" );
    }

    public void testApp() throws NamingException {

        CommentService converter = (CommentService) ctx.lookup("java:global/classes/CommentService");
        assertNotNull(converter);

        Comment t = new Comment();
        converter.create(t);
        t = new Comment();
        converter.create(t);
        t = new Comment();
        converter.create(t);
        t = new Comment();
        converter.create(t);

        Collection<Comment> ts = converter.getAll();

        assertEquals(4, ts.size());
    }
}

Next, add two dependencies (such as to a Maven POM):

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.8.2</version>
    <scope>test</scope>
    <type>jar</type>
</dependency>
<dependency>
    <groupId>org.glassfish.main.extras</groupId>
    <artifactId>glassfish-embedded-all</artifactId>
    <version>3.1.2</version>
    <scope>compile</scope>
</dependency>

Having the dependencies, session and entity bean, persistence file, test files implemented exactly as shown, then the test(s) should pass. (The examples on the Internet are woefully inadequate.)

Leave a Comment