折腾了一天,junit终于可以跑起来了,分享一下,希望对大家能有帮助。
项目基于Maven搭建(Maven确实是个好东西)。使用的技术有jsf + richfaces3.3 + seam2.2 + hibernate3.3 + jasperreport3.7。感觉seam很强大,但没有spring方便,至少在测试方面要花费一翻功夫。
我没有将测试代码放到项目的测试目录下,而是另起了一个工程,专用于测试,以下就完整的介绍一下这个过程。更多是步骤描述了,为什么要这样做就不多解释了,也没能力解释清楚。
1. 建立测试工程:seamtest。最简单的maven工程即可。这里不介绍如何在eclipse中集成maven,读者可以搜搜m2eclipse,这是一个eclipse插件。
2. 配置seamtest的pom.xml,增加如下三个依赖:
<dependency>
<groupId>org.jboss.seam.embedded</groupId>
<artifactId>hibernate-all</artifactId>
<version>beta3.SP10</version>
</dependency>
<dependency>
<groupId>org.jboss.seam.embedded</groupId>
<artifactId>jboss-embedded-all</artifactId>
<version>beta3.SP10</version>
</dependency>
<dependency>
<groupId>org.jboss.seam.embedded</groupId>
<artifactId>thirdparty-all</artifactId>
<version>beta3.SP10</version>
</dependency>
3. 这三个依赖需要从jboss仓库下载,可以访问这个站点:https://repository.jboss.org/nexus/index.html,然后根据上面提供的构件Id进行搜索,或者直接将仓库指向:https://repository.jboss.org/nexus/content/repositories/releases/。如何在settings.xml文件中配置仓库地址不难,google下吧。
4. 将需要测试的项目及junit加到maven依赖中,我的配置为:
<dependency>
<groupId>cn.terry</groupId>
<artifactId>target-web</artifactId>
<version>0.0.1-SNAPSHOT</version>
<type>war</type>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
<type>jar</type>
</dependency>
上面的“target-web”就是我要测试的基于maven构建的项目。
5. 保存配置后等待eclipse下载完所有依赖的jar包。
6. 将目标工程加到测试工程的依赖工程中。参考下图:
7. 下载Embedded JBoss,下载地址:
http://sourceforge.net/projects/jboss/files/Embedded%20JBoss/Embedded%20JBoss%20Beta%203/。
8. 解压缩下载的压缩后,找到文件夹:bootstrap,除这个文件夹外,其它下载文件在我们这个案例里面都不需要用到。
9. 将bootstrap文件夹链接到测试工程的source下面,参考如下操作界面:
10. 将target-web的webapp目录链接到测试工程的source下面,这一步比较奇怪,不多解释了,照着做就行了。
11. 配置DataSource。在bootstrap/deploy下面有文件hsqldb-ds.xml,注意文件名的结尾部分是“-ds.xml”,你可以按这个命名规则建立自己需要的datasource文件,如oracle-ds.xml。datasource文件具体怎么写,就要参考hsqldb-ds.xml了,这个还是比较容易的。如果你的项目不需要dataSource的话就跳过这一步吧。
12. 接下来开始写测试代码了,如下二个类直接复制过去用:
MySeamTestBase: 其它测试类可以直接继承该类
package cn.terry.test;
import java.util.Properties;
import org.jboss.seam.mock.AbstractSeamTest;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class MySeamTestBase extends AbstractSeamTest {
// static helper instance to call non static methods in
// a static method
private static MySeamTestBase seamTest = new MySeamTestBase();
private static boolean batch = false;
/*
* JUnit test life cycle methods.
*/
@BeforeClass
public static void setUpBeforeClass() throws Exception {
if (!batch) {
seamTest.startContainer();
}
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
if (!batch)
seamTest.stopContainer();
}
@Before
public void setUp() throws Exception {
setupClass();
begin();
}
@After
public void tearDown() throws Exception {
end();
cleanupClass();
}
/*
* Helper methods
*/
// starts the JBoss embedded ejb container
public void startContainer() throws Exception {
super.startSeam();
}
// stops the JBoss embedded ejb container
public void stopContainer() throws Exception {
super.stopSeam();
}
public boolean isBatch() {
return batch;
}
// used by a JUnit.Suite runner to set the batch flag
public void setBatch(boolean fBatch) {
batch = fBatch;
}
}
MySuiteRunner, 批量执行多个测试类:
package cn.terry.test;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import cn.terry.test.testcase.HelloTest;
@Suite.SuiteClasses({
HelloTest.class
})
@RunWith(Suite.class)
public class MySuiteRunner {
private static MySeamTestBase seamTest = new MySeamTestBase();
@BeforeClass
public static void setUpBeforeClass() throws Exception {
// set the flag to signal batch mode
seamTest.setBatch(true);
seamTest.startContainer();
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
seamTest.stopContainer();
seamTest.setBatch(false);
}
}
下面的HelloTest是一个具体的测试类,模仿着写就行了:
package cn.terry.test.testcase;
import org.junit.Test;
import cn.terry.test.MySeamTestBase;
public class HelloTest extends MySeamTestBase {
@Test
public void testRollback() throws Exception{
new FacesRequest() {
protected void invokeApplication() throws Exception {
Object seamInstance = getInstance("instanceName");
}
}.run();
}
}
FacesRequest里面还有许多方法可以重写,自己翻翻手册吧。
13. 到执行这一步了,也不容易,如果是jdk6的话,要在运行时加上运行参数:-Dsun.lang.ClassLoader.allowArraySyntax=true。eclipse中如何配置请参考如下界面:
点击run,享受成果吧。
14,可能没有这么幸运,数据库连接池可能没有初始化。在我们的项目中,连接池是在一个servlet listener中初始化的,通过如上方式运行就没法自动初始化,导致测试时出现数据库连接失败的情况,这时候需要自己写些代码去初始化连接了。
总结:整个过程可能会出现没完没了的异常,别放弃,多google,总会成功的。