我正在对EJB 3.1的单元测试进行一项小型研究。最后,我的目标是为单元测试EJB 3.1生成一个易于使用的解决方案。
我希望我能为单元测试EJB制作一个完整的解决方案,一旦完成,我就可以在这个论坛上分享。
感谢您的支持。
答案 0 :(得分:14)
我对你的建议是不要陷入我看到的常见陷阱,即认为你需要在模拟和使用嵌入式EJB容器之间进行选择。
您可以同时使用它们,您应该同时使用它们,并且在您发现难以同时使用它们的情况下,您应该要求EJB容器提供更好的支持和更多功能。
当然,你会发现OpenEJB的人真的很支持并且非常乐意添加功能来支持两全其美。几乎所有非常好的功能都围绕着用户的要求创建,这些用户试图做非常具体的事情并且很难找到它。
package org.superbiz.stateless.basic;
import junit.framework.TestCase;
import javax.ejb.embeddable.EJBContainer;
public class CalculatorTest extends TestCase {
private CalculatorBean calculator;
/**
* Bootstrap the Embedded EJB Container
*
* @throws Exception
*/
protected void setUp() throws Exception {
EJBContainer ejbContainer = EJBContainer.createEJBContainer();
Object object = ejbContainer.getContext().lookup("java:global/simple-stateless/CalculatorBean");
assertTrue(object instanceof CalculatorBean);
calculator = (CalculatorBean) object;
}
完整来源here
这将扫描类路径并加载所有bean。
在代码中定义所有内容的方法略有不同。显然,模拟更容易,因为你可以随意提供bean的模拟实现。
@RunWith(ApplicationComposer.class)
public class MoviesTest extends TestCase {
@EJB
private Movies movies;
@Resource
private UserTransaction userTransaction;
@PersistenceContext
private EntityManager entityManager;
@Module
public PersistenceUnit persistence() {
PersistenceUnit unit = new PersistenceUnit("movie-unit");
unit.setJtaDataSource("movieDatabase");
unit.setNonJtaDataSource("movieDatabaseUnmanaged");
unit.getClazz().add(Movie.class.getName());
unit.setProperty("openjpa.jdbc.SynchronizeMappings", "buildSchema(ForeignKeys=true)");
return unit;
}
@Module
public EjbJar beans() {
EjbJar ejbJar = new EjbJar("movie-beans");
ejbJar.addEnterpriseBean(new StatefulBean(MoviesImpl.class));
return ejbJar;
}
@Configuration
public Properties config() throws Exception {
Properties p = new Properties();
p.put("movieDatabase", "new://Resource?type=DataSource");
p.put("movieDatabase.JdbcDriver", "org.hsqldb.jdbcDriver");
p.put("movieDatabase.JdbcUrl", "jdbc:hsqldb:mem:moviedb");
return p;
}
@Test
public void test() throws Exception {
userTransaction.begin();
try {
entityManager.persist(new Movie("Quentin Tarantino", "Reservoir Dogs", 1992));
entityManager.persist(new Movie("Joel Coen", "Fargo", 1996));
entityManager.persist(new Movie("Joel Coen", "The Big Lebowski", 1998));
List<Movie> list = movies.getMovies();
assertEquals("List.size()", 3, list.size());
for (Movie movie : list) {
movies.deleteMovie(movie);
}
assertEquals("Movies.getMovies()", 0, movies.getMovies().size());
} finally {
userTransaction.commit();
}
}
}
很容易将注意力集中在不同类型的测试之间的差异等等,但对于一个实用的中间部分来说肯定会有所说。我个人认为能够尽可能流畅地混合“单元”和“集成”样式没有任何问题。
当然,这是一个令人钦佩的目标。非常欢迎让我们更接近的想法和功能要求。
答案 1 :(得分:5)
实际上,您可能需要考虑两种不同类型的测试(非独占):
答案 2 :(得分:3)
您可以使用Needle进行Java EE组件的单元测试。
Needle是一个轻量级框架,用于隔离地测试容器外部的Java EE组件。它通过分析依赖关系和自动注入模拟对象来减少测试设置代码。