At line 210 added 113 lines. |
|
以上是我们使用JUnit测试而初始化和销毁PersonDao的基本代码,对象ctx引用了Spring的ApplicationContext,它在[BaseDaoTestCase|http://raibledesigns.com/downloads/appfuse/api/org/appfuse/dao/BaseDaoTestCase.java.html]类的静态代码区里被初始化。 |
|
现在我们需要实际测试DAO中的CRUD(create, retrieve, update, delete)方法,为此我们需要为每个方法建立以test(全部小写)开头的测试方法,只要这个方法是公共的,返回类型是void,它们就会被我们build.xml中的Ant的<junit>任务<junit>调用,如下是一些简单的CRUD测试,需要注意的一点是所有的方法(或者叫做测试)必须是自治的,添加如下代码到文件{{PersonDaoTest.java}}: |
|
[{Java2HtmlPlugin |
|
public void testGetPerson() throws Exception { |
person = new Person(); |
person.setFirstName("Matt"); |
person.setLastName("Raible"); |
|
dao.savePerson(person); |
assertNotNull(person.getId()); |
|
person = dao.getPerson(person.getId()); |
assertEquals(person.getFirstName(), "Matt"); |
} |
|
public void testSavePerson() throws Exception { |
person = dao.getPerson(new Long(1)); |
person.setFirstName("Matt"); |
|
person.setLastName("Last Name Updated"); |
|
dao.savePerson(person); |
|
if (log.isDebugEnabled()) { |
log.debug("updated Person: " + person); |
} |
|
assertEquals(person.getLastName(), "Last Name Updated"); |
} |
|
public void testAddAndRemovePerson() throws Exception { |
person = new Person(); |
person.setFirstName("Bill"); |
person.setLastName("Joy"); |
|
dao.savePerson(person); |
|
assertEquals(person.getFirstName(), "Bill"); |
assertNotNull(person.getId()); |
|
if (log.isDebugEnabled()) { |
log.debug("removing person..."); |
} |
|
dao.removePerson(person.getId()); |
|
try { |
person = dao.getPerson(person.getId()); |
fail("Person found in database"); |
} catch (DataAccessException dae) { |
log.debug("Expected exception: " + dae.getMessage()); |
assertNotNull(dae); |
} |
} |
}] |
|
|
;:%%(color: blue)''在testGetPerson方法,我们创建了一个person并且调用get方法,我通常会增加一条我所需要的记录到数据库,因为在测试运行之前[DBUnit|http://www.dbunit.org]会为数据库准备测试数据,我们可以简单的在metadata/sql/sample-data.xml里添加测试所必须的记录''%% |
|
<div style="color: blue !important; margin-left: 50px"> |
{{{ |
<table name='person'> |
<column>id</column> |
<column>first_name</column> |
<column>last_name</column> |
<row> |
<value>1</value> |
<value>Matt</value> |
<value>Raible</value> |
</row> |
</table> |
}}} |
</div> |
|
;:%%(color: blue)''通过这种方式你可以在testGetPerson方法里消除创建新纪录的动作,如果你愿意直接插入记录到数据库(使用SQL或者GUI),你可以用__ant db-export__和__cp {{db-export.xml metadata/sql/sample-data.xml}}__重新构建你的{{sample-data.xml}}文件。''%% |
|
在上面的例子里,你可以看到我们调用person.set*(value)来准备我们需要保存的对象,在这个例子里很简单,但是当你要插入10条必添字段(not-null="true")时就比较麻烦了,这就是我为什么要在BaseDaoTestCase使用ResourceBundle文件,只要在{{PersonDaoTest.java}}同一个目录创建一个{{PersonDaoTest.properties}}并且在里面定义你的属性值: |
;:%%(color: blue)''我通常只是在Java里硬编码,但是这个.properties对于大对象很有用。''%% |
{{{ |
firstName=Matt |
lastName=Raible |
}}} |
此时,你要通过调用BaseDaoTestCase.populate(java.lang.Object)方法来准备对象,而不是使用person.set*。 |
|
[{Java2HtmlPlugin |
|
person = new Person(); |
person = (Person) populate(person); |
}] |
|
在目前情况下,还不可以编译PersonDaoTest,因为在类路径里还没有PersonDao.class,我们需要创建它。PersonDAO.java是一个接口,PersonDAOHibernate.java是它的Hibernate实现,让我们继续,开始创建。 |
|
!!创建一个对对象执行CRUD操作的新DAO[#4] |
马上,在{{src/dao/**/dao}}目录里建立PersonDao.java接口,并且指定所有实现类要实现的基本CRUD操作,为了显示方便,我已经去掉了所有JavaDocs。 |
|
[{Java2HtmlPlugin |
|
package org.appfuse.dao; |
|
import org.appfuse.model.Person; |
|
public interface PersonDao extends Dao { |
public Person getPerson(Long personId); |
public void savePerson(Person person); |
public void removePerson(Long personId); |
} |
}] |
|
注意,在以上的方法声明上并没有exceptions说明,这是因为[Spring|http://www.springframework.org]使用RuntimeExceptions来包裹Exceptions的方式,此时,你已经可以使用__ant compile-dao__来编译{{src/dao}}和{{test/dao}}下的所有源文件,然而当你运行__ant test-dao -Dtestcase=PersonDao__进行测试时,你会得到一个错误:<span style="color: red">No bean named 'personDao' is defined</span>,这是一个Spring的错误,说明你必须在{{applicationContext-hibernate.xml}}指定一个名字为''personDAO''的bean,在此之前我们需要创建PersonDao的实现类。 |