前面还记得有前辈说过看一个开源项目在不懂的情况下要去努力的去看它的单元测试,这样就能更好的领悟作者的思想。首先我们先看一下单元测试用的一些xml。
<!-- Test1.xml -->
<?xml version="1.0"?>
<employee firstName="First Name" lastName="Last Name">
<address type="home" street="Home Street" city="Home City"
state="HS" zipCode="HmZip"/>
<address type="office" street="Office Street" city="Office City"
state="OS" zipCode="OfZip"/>
</employee>
首先来看第一个单元测试:
package org.apache.commons.digester;
import java.io.InputStream;
import java.io.IOException;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
/**
* <p>Test Case for the Digester class. These tests perform parsing of
* XML documents to exercise the built-in rules.</p>
*
* @author Craig R. McClanahan
* @version $Revision: 1.5 $ $Date: 2001/10/11 00:28:42 $
*/
public class RuleTestCase extends TestCase {
// ----------------------------------------------------- Instance Variables
/**
* The digester instance we will be processing.
*/
protected Digester digester = null;
// ----------------------------------------------------------- Constructors
/**
* Construct a new instance of this test case.
*
* @param name Name of the test case
*/
public RuleTestCase(String name) {
super(name);
}
// --------------------------------------------------- Overall Test Methods
/**
* Set up instance variables required by this test case.
*/
public void setUp() {
digester = new Digester();
}
/**
* Return the tests included in this test suite.
*/
public static Test suite() {
return (new TestSuite(RuleTestCase.class));
}
/**
* Tear down instance variables required by this test case.
*/
public void tearDown() {
digester = null;
}
// ------------------------------------------------ Individual Test Methods
/**
* Test object creation (and associated property setting) with nothing on
* the stack, which should cause an appropriate Employee object to be
* returned.
*/
public void testObjectCreate1() {
// Configure the digester as required
digester.addObjectCreate("employee",
"org.apache.commons.digester.Employee");
digester.addSetProperties("employee");
// Parse our test input.
Object root = null;
try {
root = digester.parse(getInputStream("Test1.xml"));
} catch (Throwable t) {
fail("Digester threw IOException: " + t);
}
// 测试非空
assertNotNull("Digester returned an object", root);
// 测试栈顶的元素时候Employee或者时候他的子类型
assertTrue("Digester returned an Employee",
root instanceof Employee);
Employee employee = (Employee) root;
// 测试firstName和lastName有没有被正确的设置
assertEquals("First name is correct",
"First Name",
employee.getFirstName());
assertEquals("Last name is correct",
"Last Name",
employee.getLastName());
}
/**
* Test object creation (and associated property setting) with nothing on
* the stack, which should cause an appropriate Employee object to be
* returned. The processing rules will process the nested Address elements
* as well, but will not attempt to add them to the Employee.
*/
public void testObjectCreate2() {
// Configure the digester as required
digester.addObjectCreate("employee",
"org.apache.commons.digester.Employee");
digester.addSetProperties("employee");
digester.addObjectCreate("employee/address",
"org.apache.commons.digester.Address");
digester.addSetProperties("employee/address");
// Parse our test input.
Object root = null;
try {
root = digester.parse(getInputStream("Test1.xml"));
} catch (Throwable t) {
fail("Digester threw IOException: " + t);
}
// 测试非空
assertNotNull("Digester returned an object", root);
// 测试栈顶的元素是不是Employee或者是它的子类
assertTrue("Digester returned an Employee",
root instanceof Employee);
// 测试firstName和lastName有没有被正确设置
Employee employee = (Employee) root;
assertEquals("First name is correct",
"First Name",
employee.getFirstName());
assertEquals("Last name is correct",
"Last Name",
employee.getLastName());
}
/**
* Test object creation (and associated property setting) with nothing on
* the stack, which should cause an appropriate Employee object to be
* returned. The processing rules will process the nested Address elements
* as well, and will add them to the owning Employee.
*/
public void testObjectCreate3() {
// Configure the digester as required
digester.addObjectCreate("employee",
"org.apache.commons.digester.Employee");
digester.addSetProperties("employee");
digester.addObjectCreate("employee/address",
"org.apache.commons.digester.Address");
digester.addSetProperties("employee/address");
digester.addSetNext("employee/address",
"addAddress");
// Parse our test input once
Object root = null;
try {
root = digester.parse(getInputStream("Test1.xml"));
} catch (Throwable t) {
fail("Digester threw IOException: " + t);
}
validateObjectCreate3(root);
// Parse the same input again
try {
root = digester.parse(getInputStream("Test1.xml"));
} catch (Throwable t) {
fail("Digester threw IOException: " + t);
}
validateObjectCreate3(root);
}
/**
* Same as testObjectCreate1(), except use individual call method rules
* to set the properties of the Employee.
*/
public void testObjectCreate4() {
// Configure the digester as required
digester.addObjectCreate("employee",
"org.apache.commons.digester.Employee");
digester.addCallMethod("employee",
"setFirstName", 1);
digester.addCallParam("employee", 0, "firstName");
digester.addCallMethod("employee",
"setLastName", 1);
digester.addCallParam("employee", 0, "lastName");
// Parse our test input.
Object root = null;
try {
root = digester.parse(getInputStream("Test1.xml"));
} catch (Throwable t) {
fail("Digester threw IOException: " + t);
}
// 测试非空和类型检验
assertNotNull("Digester returned an object", root);
assertTrue("Digester returned an Employee",
root instanceof Employee);
// 测试了CallMethodRule和CallParamRule没有能被正确调用
Employee employee = (Employee) root;
assertEquals("First name is correct",
"First Name",
employee.getFirstName());
assertEquals("Last name is correct",
"Last Name",
employee.getLastName());
}
/**
* It should be possible to parse the same input twice, and get trees
* of objects that are isomorphic but not be identical object instances.
*/
public void testRepeatedParse() {
// 这个主要时候测试重复的parse后生成的元素时候不同的。
// Configure the digester as required
digester.addObjectCreate("employee",
"org.apache.commons.digester.Employee");
digester.addSetProperties("employee");
digester.addObjectCreate("employee/address",
"org.apache.commons.digester.Address");
digester.addSetProperties("employee/address");
digester.addSetNext("employee/address",
"addAddress");
// Parse our test input the first time
Object root1 = null;
try {
root1 = digester.parse(getInputStream("Test1.xml"));
} catch (Throwable t) {
fail("Digester #1 threw Exception: " + t);
}
validateObjectCreate3(root1);
// Parse our test input the second time
Object root2 = null;
try {
root2 = digester.parse(getInputStream("Test1.xml"));
} catch (Throwable t) {
fail("Digester #2 threw Exception: " + t);
}
validateObjectCreate3(root2);
// Make sure that it was a different root
assertTrue("Different tree instances were returned",
root1 != root2);
}
/**
* Test object creation (and associated property setting) with nothing on
* the stack, which should cause an appropriate Employee object to be
* returned. The processing rules will process the nested Address elements
* as well, but will not attempt to add them to the Employee.
*/
public void testRuleSet1() {
// Configure the digester as required
RuleSet rs = new TestRuleSet();
digester.addRuleSet(rs);
// Parse our test input.
Object root = null;
try {
root = digester.parse(getInputStream("Test1.xml"));
} catch (Throwable t) {
fail("Digester threw IOException: " + t);
}
// 主要时候测试使用RuleSet时候Rule能被正确的解析和执行
assertNotNull("Digester returned an object", root);
assertTrue("Digester returned an Employee",
root instanceof Employee);
Employee employee = (Employee) root;
assertEquals("First name is correct",
"First Name",
employee.getFirstName());
assertEquals("Last name is correct",
"Last Name",
employee.getLastName());
assertNotNull("Can retrieve home address",
employee.getAddress("home"));
assertNotNull("Can retrieve office address",
employee.getAddress("office"));
}
/**
* Same as <code>testRuleSet1</code> except using a single namespace.
*/
public void testRuleSet2() {
// Configure the digester as required
digester.setNamespaceAware(true);
RuleSet rs = new TestRuleSet(null,
"http://jakarta.apache.org/digester/Foo");
digester.addRuleSet(rs);
// Parse our test input.
Object root = null;
try {
root = digester.parse(getInputStream("Test2.xml"));
} catch (Throwable t) {
fail("Digester threw IOException: " + t);
}
assertNotNull("Digester returned an object", root);
assertTrue("Digester returned an Employee",
root instanceof Employee);
Employee employee = (Employee) root;
assertEquals("First name is correct",
"First Name",
employee.getFirstName());
assertEquals("Last name is correct",
"Last Name",
employee.getLastName());
assertNotNull("Can retrieve home address",
employee.getAddress("home"));
assertNotNull("Can retrieve office address",
employee.getAddress("office"));
}
/**
* Same as <code>testRuleSet2</code> except using a namespace
* for employee that we should recognize, and a namespace for
* address that we should skip.
*/
public void testRuleSet3() {
// Configure the digester as required
digester.setNamespaceAware(true);
RuleSet rs = new TestRuleSet(null,
"http://jakarta.apache.org/digester/Foo");
digester.addRuleSet(rs);
// Parse our test input.
Object root = null;
try {
root = digester.parse(getInputStream("Test3.xml"));
} catch (Throwable t) {
fail("Digester threw IOException: " + t);
}
assertNotNull("Digester returned an object", root);
assertTrue("Digester returned an Employee",
root instanceof Employee);
Employee employee = (Employee) root;
assertEquals("First name is correct",
"First Name",
employee.getFirstName());
assertEquals("Last name is correct",
"Last Name",
employee.getLastName());
// 这个主要时候测试把namespaceURL不添加到上面,其实通过这个testcase我们
// 可以看到RuleSet里面的namespaceURI的作用了,它会给加到他里面的所有的
// rule都加上这个namespaceURI,然后将这个namespaceURI应用到所有的rule
// 上面,在获得rule的时候只会得到相匹配的rule,起到一个过滤功能
assertNull("Can not retrieve home address",
employee.getAddress("home"));
assertNull("Can not retrieve office address",
employee.getAddress("office"));
}
// ------------------------------------------------ Utility Support Methods
/**
* Return an appropriate InputStream for the specified test file (which
* must be inside our current package.
*
* @param name Name of the test file we want
*
* @exception IOException if an input/output error occurs
*/
protected InputStream getInputStream(String name) throws IOException {
return (this.getClass().getResourceAsStream
("/org/apache/commons/digester/" + name));
}
/**
* Validate the assertions for ObjectCreateRule3.
*
* @param object Root object returned by <code>digester.parse()</code>
*/
protected void validateObjectCreate3(Object root) {
// 检验Employee的信息
// Validate the retrieved Employee
assertNotNull("Digester returned an object", root);
assertTrue("Digester returned an Employee",
root instanceof Employee);
Employee employee = (Employee) root;
assertEquals("First name is correct",
"First Name",
employee.getFirstName());
assertEquals("Last name is correct",
"Last Name",
employee.getLastName());
// 检验名称时候home的address元素的相关属性
// Validate the corresponding "home" Address
Address home = employee.getAddress("home");
assertNotNull("Retrieved home address", home);
assertEquals("Home street", "Home Street",
home.getStreet());
assertEquals("Home city", "Home City",
home.getCity());
assertEquals("Home state", "HS",
home.getState());
assertEquals("Home zip", "HmZip",
home.getZipCode());
// 检验名称叫office的address的相关属性
// Validate the corresponding "office" Address
Address office = employee.getAddress("office");
assertNotNull("Retrieved office address", office);
assertEquals("Office street", "Office Street",
office.getStreet());
assertEquals("Office city", "Office City",
office.getCity());
assertEquals("Office state", "OS",
office.getState());
assertEquals("Office zip", "OfZip",
office.getZipCode());
}
}