Arquillian测试框架快速上手教程(三)- 使用 Arquillian 进行Java持久化测试

本系列教程共五篇,分别是:

一、环境搭建、容器适配、单元测试

二、JBoss Forge、ShinkWrap快速指南

三、使用 Arquillian进行Java持久化测试

四、使用Arquillian + Drone + Selenium + Graphene 进行Web自动化测试

五、使用 Arquillian 在云端进行测试

其中,Web容器以JBoss-as-7.1.1为例,工程以maven目录结构为准。


本文所涉及到的内容有:

1. JPA

2. Arquillian

3. Maven

4. JUnit

5. PostgreSql


添加JPA相关依赖

这里我们沿用上一篇文章的项目目录结构和配置。数据库使用PostgreSql-9.1,以Hibernate为JPA具体实现。打开 arquillian-demo 的pom.xml,在 dependencies 节点中添加以下内容:
 
<dependencies>
		<!-- JPA -->
		<dependency>
			<groupId>org.hibernate.javax.persistence</groupId>
			<artifactId>hibernate-jpa-2.0-api</artifactId>
			<version>1.0.1.Final</version>
		</dependency>

		<!-- hibernate -->
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-entitymanager</artifactId>
			<version>4.0.1.Final</version>
		</dependency>
		
		<!-- log4j -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>1.6.1</version>
		</dependency>

		<!-- JDBC Driver -->
		<dependency>
            <groupId>postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>9.1-901.jdbc4</version>
        </dependency>
	</dependencies>


编写 Entity Bean 和测试 Bean

Entity Bean:

我们在 cn.demo 包下创建一个最简单的 Entity Bean:

package cn.demo;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Member {
	@Id @GeneratedValue
	private Integer id;
	private String username;
	
	public Member() {} // 提供空构造函数
	public Member(String name) {
		this.username = name;
	}
	
	@Override
	public String toString() {
		return this.username;
	}
	
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}

}

Test Bean:

Test Bean依然需要"三大件",即 @Deployment、@RunWith(Arquillian.class) 和 @Test。

@RunWith(Arquillian.class)
public class MemberTest {
	@Inject
	private UserTransaction ut;
	@PersistenceContext(unitName = "test")
	private EntityManager em;
	
	private static String[] members = {"Bruce", "Neo", "Kitty"};
	private static final String QUERY_SQL = "select m from Member m";

	@Deployment
	public static WebArchive deploy() {
		WebArchive war = ShrinkWrap.create(WebArchive.class, "MemberTest.war")
				.addPackage(Member.class.getPackage()) // 将 Member.class 和其所在的包一并添加进去
				.addAsResource("test-persistence.xml", "META-INF/persistence.xml") // 添加 persistent unit 配置文件
				.addAsWebInfResource("jboss-ds.xml") // 添加 DataSource 声明文件
				.addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
		
		// 调用war的toString(true)方法可以将打包后的目录结构输出到控制台
		System.out.println(war.toString(true));
		
		return war;
	}
	
	// ... ...


由于我们是在JBoss中运行测试,因此我们需要先向JBoss注册一个数据源,以声明数据的来源。向JBoss注册数据源有2种方式,一是编辑standalone.xml 文件,添加 data-srouce节点,另一种是在项目中创建 *-ds.xml文件,JBoss会在应用部署的时候自动读取这个文件,动态注册数据源。这里我们采用第二种方式。

在src/test/resources目录下新建 jboss-ds.xml ,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<datasources xmlns="http://www.jboss.org/ironjacamar/schema"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="
        http://www.jboss.org/ironjacamar/schema
        http://docs.jboss.org/ironjacamar/schema/datasources_1_0.xsd">
	<datasource enabled="true" jndi-name="jdbc/arquillian" <!-- 数据源的 JNDI 查找名称 -->
		pool-name="ArquillianEmbeddedH2Pool">
		<!-- jap-test 数据库必须事先创建 -->
		<connection-url>jdbc:postgresql://localhost:5432/jpa-test</connection-url>
		<!-- 该dirver必须在JBoss的standalone.xml中声明 -->
		<driver>postgresql</driver>
		<security>
			<user-name>postgres</user-name>
			<password>111111</password>
		</security>
	</datasource>
</datasources>

然后在同样的目录下新建 test-persistence.xml(使用ShrinkWarp部署时会将其动态更名为persistence.xml) 文件:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
	xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="
        http://java.sun.com/xml/ns/persistence
        http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
	<persistence-unit name="test" transaction-type="JTA">
		<!-- 此处必须与 jboss-ds.xml文件中的jndi-name节点内容一致 -->
		<jta-data-source>jdbc/arquillian</jta-data-source>
		<properties>
			<property name="hibernate.hbm2ddl.auto" value="create-drop" />
			<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" />
			<property name="hibernate.show_sql" value="true" />
			<property name="hibernate.format_sql" value="true" />
		</properties>
	</persistence-unit>
</persistence>

说明:
1. 因为程序的运行环境为JBoss,所以 "transaction-type" 必须指定为 "JTA"。如果是非容器环境,该属性应为 " RESOURCE_LOCAL"(也是默认值)。
2. 如果使用PostgreSql,则 "hibernate.dialect" 属性必须指定为 "org.hibernate.dialect.PostgreSQLDialect", 否则运行时会报语法错误。
3. 如果 "hibernate.hbm2dll.auto" 属性为 "update",那么数据库中必须事先存在相应的表,否则会报错。


接下来编辑测试代码。程序逻辑很简单,先清除member表中的源有记录,然后插入新记录,最后从数据库中取出数据,验证结果。

@Test方法代码如下:
@Test
	public void test() throws Exception {
		ut.begin();
	
		System.out.println("正在查询 ...");
		List<Member> memberList = em.createQuery(QUERY_SQL)
				.getResultList();
		
		ut.commit();
		
		Assert.assertTrue(validateData(memberList));
	
	}

在运行Test之前,我们需要先清除表中原有数据。这时候我们可以定义一个prepareTest()方法,并对其添加  @Before 注解。标有该注解的方法会在 @Test 方法之前执行。同样, JUnit还提供 @After 注解,标有 @After 的方法会在所有的 @Test 方法执行完后运行。

@Before
	public void prepareTest() throws Exception {
		clearData(); // 清理表中原有数据
		insertData(); // 插入新记录
	}

然后是自定义的 clearData() 方法和 insertData()方法:
/**
	 * 向Member表中插入3条记录
	 * @throws Exception
	 */
	private void insertData() throws Exception {
		ut.begin();
		
		System.out.println("插入记录 ...");
		for(String name : members) {
			Member mem = new Member(name);
			em.persist(mem);;
		}
		
		ut.commit();
	}
	
	/**
	 * 将member表中的原有数据清除。
	 * @throws Exception
	 */
	private void clearData() throws Exception {
		ut.begin();
		
		System.out.println("清理旧数据 ...");
		em.createQuery("delete from Member")
			.executeUpdate();
		
		ut.commit();

	}

最后是 validateData() 方法,其作用是验证取出的数据,看看是否与我们插入的数据相同。
/**
	 * 判断List对象中是否包含了members数据中所有的元素。
	 * @param list 数据库查询结果
	 * @return 全部包含返回true, 反之为false
	 */
	private boolean validateData(List<Member> list) {
		Set<String> nameSet = new HashSet<String>();
		for(Member mem : list) {
			System.out.println("取出数据:" + mem.getUsername());
			nameSet.add(mem.getUsername());
		}
		
		return nameSet.containsAll(Arrays.asList(members));
	}


运行测试

到这里项目的目录结构应该如下图所示:
Arquillian测试框架快速上手教程(三)- 使用 Arquillian 进行Java持久化测试_第1张图片

先启动JBoss7,然后切换到项目目录下,执行
mvn clean install -Dmaven.test.skip=true
mvn test -Parq-jbossas-remote

看到如下输出即测试成功。
Arquillian测试框架快速上手教程(三)- 使用 Arquillian 进行Java持久化测试_第2张图片

你可能感兴趣的:(Arquillian测试框架快速上手教程(三)- 使用 Arquillian 进行Java持久化测试)