如果我能使用IntelliJ的TestNG插件那就太好了,但我还在4.5版本上,它只适用于IDEA 5。尝试过几次切换,但XML编辑器根本不起作用,还抛出异常,速度比我点击还快。我想回到IDEA 3.x的XML编辑器,它只是工作,而且没有4.x中的愚蠢缩进...
尽管如此,只用TestNG测试了一两天,我就觉得它比JUnit好得多,我真的很想知道为什么我以前没有尝试过。我想我应该听从Gavin的话,他对如何轻松地将Seam测试设置起来赞不绝口。它实际上有我一直在JUnit中缺少的所有功能。
所以我为CaveatEmptor设置了第一个TestNG环境,运行良好。顺便说一句,我已经上传了一个新的alpha版本,其中包括我将在这里讨论的所有内容(以及许多其他新功能)。对于那些对《Hibernate in Action》第二版进展感兴趣的人:我已经完成了95%的所有映射示例,我认为(并希望)这是最耗时的部分。我现在正在更新关于会话、事务、缓存等章节,所以今年完成手稿是有可能的。
回到TestNG,以及我如何使用它来测试EJB。TestNG的一个优点是配置测试所需运行时基础设施非常容易。首先,我写了一个类来启动JBoss EJB 3.0容器。TestNG将运行startup()和shutdown()方法来执行一系列测试
public class EJB3Container { private static InitialContext initialContext; private EJB3StandaloneDeployer deployer; @Configuration(beforeSuite = true) public void startup() { try { // Boot the JBoss Microcontainer with EJB3 settings, loads ejb3-interceptors-aop.xml EJB3StandaloneBootstrap.boot(null); // Deploy CaveatEmptor beans (datasource, mostly) EJB3StandaloneBootstrap.deployXmlResource("caveatemptor-beans.xml"); // Add all EJBs found in the archive that has this file deployer = new EJB3StandaloneDeployer(); deployer.getArchivesByResource().add("META-INF/persistence.xml"); // Deploy everything we got deployer.create(); deployer.start(); // Create InitialContext from jndi.properties initialContext = new InitialContext(); } catch (Exception ex) { throw new RuntimeException(ex); } } @Configuration(afterSuite = true) public void shutdown() { try { deployer.stop(); deployer.destroy(); EJB3StandaloneBootstrap.shutdown(); } catch (Exception ex) { throw new RuntimeException(ex); } } public static Object lookup(String beanName) { try { return initialContext.lookup(beanName); } catch (NamingException ex) { throw new RuntimeException("Couldn't lookup: " + beanName, ex); } } }
启动时,我启动了JBoss Microcontainer,实际上它是未来JBoss AS 5.x的内核。因为我使用的是EJB3StandaloneBootstrap它将自动搜索 EJB 3.0 容器的配置文件。您需要在类路径中包含这些文件以及所需的库。如果您想尝试此下载,请下载 CaveatEmptor并复制库和配置。
接下来,我将部署一些来自caveatemptor-beans.xml的 bean。目前这仅包括用于集成测试的单个数据源。它配置为使用 JTA 并绑定到 JNDI,由微容器提供的服务。如果您需要,可以在此处设置和连接其他无状态 POJO 服务。
最后,我将部署所有用于测试的 EJB。TheEJB3StandaloneDeployer支持许多不同的部署策略,我决定使用 搜索类路径并部署包含此文件的 JAR
。对于 EJB 3.0 持久性,我在 CaveatEmptor 中主要进行测试,我必须有一个META-INF/persistence.xml配置,以便为EntityManagerFactory。我实际上必须找出如何使用单个命令部署展开的存档并自动发现 EJB...
现在,如果我要编写一个测试类,我需要一个起点,我需要获取我的 EJB 之一。我可以在 JNDI 中查找它们——这就是静态lookup()方法的作用——或者我可以用微容器将它们连接到我的测试类中。我决定使用 lookup
public class CategoryItem { @Test(groups = {"integration.database"}) public void saveCategory() { CategoryDAO catDAO = (CategoryDAO)EJB3Container.lookup(CategoryDAO.class.getName()); Category newCat = new Category("Foo"); catDAO.makePersistent(newCat); } }
在这里,我正在测试一个数据访问对象。好吧,我实际上并没有测试很多,因为我没有在保存后断言任何状态。我仍然必须将所有我的 JUnit 测试迁移过来,但我的首要目标是使基础设施就绪。
TheCategoryDAO是一个我使用 Generic DAO 模式 编写的无状态 EJB。为了使其成为一个 EJB,我必须添加一个@Stateless注解,并将EntityManager注入到 bean 中。关于事务呢?
对于无状态 EJB,默认的事务属性是REQUIRES,因此我调用的任何 DAO 方法都在系统事务中执行。如果在同一测试方法中调用多个,它们都将运行在同一个事务中。
我还开始使用 TestNG 组,这是一个很棒的功能。通过将测试方法标记为属于组integration.database,我可以在testng.xml:
<suite name="CaveatEmptor-EJB3" verbose="1"> <test name="Runtime"> <packages> <package name="org.hibernate.ce.auction.test.testng.runtime"/> </packages> </test> <test name="Integration"> <groups> <run><include name="integration.*"/></run> </groups> <packages> <package name="org.hibernate.ce.auction.test.testng.persistence"/> </packages> </test> </suite>
中的 TestNG 套件组装中针对它。我现在还需要找出如何以某种方式创建组装,这样就说 为此组测试使用此运行时
。目前我需要为这个创建几个套件。
由于我卡在旧的 IntelliJ 中,我必须使用 Ant 运行测试(我真的很想看到那个绿色的进度条 ;)
<target name="testng.run" depends="testng.package" description="TestNG tests with the JBoss EJB3 Microcontainer"> <mkdir dir="${testng.out.dir}"/> <testng outputDir="${testng.out.dir}"> <classpath> <pathelement path="${testng.build.dir}/${proj.shortname}.jar"/> <path refid="project.classpath"/> <path> <fileset dir="${container.lib}"> <include name="**/*.jar"/> </fileset> </path> </classpath> <xmlfileset dir="${testng.classes.dir}" includes="testng.xml"/> </testng> </target>
所以我现在对 TestNG 很着迷,并将将其用于未来的所有 EJB 测试。我必须查看 Gavins 的 TestNG 配置,用于 Seam 中的 JSF + EJB 测试以及他如何模拟 HTTP 环境...
哦,如果 JetBrains 的人看到这个:修复 XML 编辑器。有些人用它来编写文档。谢谢 :)