随笔 - 23  文章 - 11  trackbacks - 0
<2009年4月>
2930311234
567891011
12131415161718
19202122232425
262728293012
3456789

常用链接

留言簿(3)

随笔分类

随笔档案

搜索

  •  

最新评论

阅读排行榜

评论排行榜

      单元测试应该是简单和直观的,而现实中的项目大多都是采用多层方式的,如EJB和hibernate的数据驱动层的中间件技术。

      unitils来源于一个尝试,就是希望能以更务实的方式来看待单元测试......

      这个指南会告诉你,什么项目可以使用unitils。 并在这个指导方针页 中你可以了解到测试的准侧和它的特点。如果您想了解如何可以配置unitils ,并得以迅速地启动,请查看cookbook

  • unitils的断言
  • unitils的模块
  • 数据库的测试
  • 数据库的自动测试
  • hibernate的测试
  • jpa的测试
  • spring的测试
  • mock object的测试
  • 今后的方向

      unitils的断言

      在开始这个指南之前我们先说明一下独立于unitils核心模块的断言。在下面的例子中,不需要进行配置,将unitils的jar包和依赖包放在你的classpath下,就可以进行测试了。

      通过反射进行断言

      一个典型的单元测试包含了结果值和期望值的比较,unitils提供了断言的方法以帮助你进行该操作,让我们看看实例2中对有着id、first name、last name属性的User类的2个实例的比较

public class User {
    private long id;
    private String first;
    private String last;

    public User(long id, String first, String last) {
        this.id = id;
        this.first = first;
        this.last = last;
    }
}

User user1 = new User(1, "John", "Doe");
User user2 = new User(1, "John", "Doe");
assertEquals(user1, user2);
    你期望这个断言是成功的,因为这两个实例含有相同的属性,但是运行的结果并非如此,应为User类并没有覆写
equals()方法,所以assertEquals是对两个实例是否相等进行判断(user1 == user2)结果导致了比较的失败。
    假设你像如下代码一样实现了equals方法
public boolean equals(Object object) {
    if (object instanceof User) {
        return id == ((User) object).id;
    }
    return false;
}

       这在你的程序逻辑中是一个合乎逻辑的实现,当两个User实例拥有相同的id的时候,那么这两个实例就是相等的。然而这种方式在你的单元测试中并不合适,并不能通过id的相同来认为两个user是相同的。

User user1 = new User(1, "John", "Doe");
User user2 = new User(1, "Jane", "Smith");
assertEquals(user1, user2);

       这个断言将会成功,但这并不是你所期望的,因此不要使用assertEquals来对两个对象进行判定是否相等(外覆类和java.lang.String类除外)。要想断言他们相等,一种方法就是断言每个属性相等。

User user1 = new User(1, "John", "Doe");
User user2 = new User(1, "John", "Doe");
assertEquals(user1.getId(), user2.getId());
assertEquals(user1.getFirst(), user2.getFirst());
assertEquals(user1.getLast(), user2.getLast());

       unitils提供了一些方法来帮助你执行断言更加的简单,通过反射,使用ReflectionAssert.assertRefEquals上面的代码重写如下:

User user1 = new User(1, "John", "Doe");
User user2 = new User(1, "John", "Doe");
assertRefEquals(user1, user2);
   这个断言将通过反射对两个实例中的每个属性都进行比较,先是id、然后是first name、最后是last name。
   如果一个属性本身也是一个对象,那么将会使用反射进行递归比较,这同样适合与集合、map、和数组之间的比较,他们
的每个元素会通过反射进行比较。如果值是一个基本类型或者是一个外覆类,那么将会使用==进行值的比较,因此下面的断
言会取得成功
assertRefEquals(1, 1L); 

List<Double> myList = new ArrayList<Double>();
myList.add(1.0);
myList.add(2.0);
assertRefEquals(Arrays.asList(1, 2), myList);

      宽松的断言

     出于可维护性,这一点是十分重要的,举例说明:如果你要计算一个帐户的余额,那你就没比较检查这个帐户的名称。他只会增加复杂性,使之更难理解。如果你想让你的测试代码更容易生存,更容易重构的话,那请确保你断言的范围。

      宽松的顺序

      在比较集合和数组的时候你可能并不关心他们中元素的顺序,通过使用ReflectionAssert.assertRefEquals方法并配合ReflectionComparatorMode.LENIENT_ORDER参数将忽略元素的顺序。

List<Integer> myList = Arrays.asList(3, 2, 1);
assertRefEquals(Arrays.asList(1, 2, 3), myList, LENIENT_ORDER);
   无视默认
   第二种的从宽方式是使用ReflectionComparatorMode.IGNORE_DEFAULTS模式,当这种模式被设置的时候,java
的默认值,如null、0、false将会不参与断言(忽略)。
   举个例子,如果你有一个User类,该类有着first name,last name,street等属性,但是你仅仅想对first name
和street进行检查而忽略其他的属性。
User actualUser   = new User("John", "Doe", new Address("First street", "12", "Brussels"));
User expectedUser = new User("John",  null, new Address("First street", null,       null));
assertRefEquals(expectedUser, actualUser, IGNORE_DEFAULTS);

      你所期望忽略的属性的对象必须放在断言左边,如果放在右边那么依然进行比较。

assertRefEquals(null, anyObject, IGNORE_DEFAULTS);  // Succeeds
assertRefEquals(anyObject, null, IGNORE_DEFAULTS);  // Fails

      宽松的日期

      第三种从宽处理是ReflectionComparatorMode.LENIENT_DATES,当两个日期都是值,或者都是null的时候,实际的日期将会被忽略(即断言为相等)。

Date actualDate =   new Date(44444);
Date expectedDate = new Date();
assertRefEquals(expectedDate, actualDate, LENIENT_DATES);

      assertLenEquals

      ReflectionAssert还提供了一种断言,他提供宽松的顺序又提供无视的忽略。

List<Integer> myList = Arrays.asList(3, 2, 1);
assertLenEquals(Arrays.asList(1, 2, 3), myList); 

assertLenEquals(null, "any");  // Succeeds
assertLenEquals("any", null);  // Fails

      属性断言

      assertLenEqualsassertRefEquals都是比较对象,ReflectionAssert也提供方法对对象的属性进行比较。(依赖与ONGL)。

      一些属性比较的例子

assertPropertyLenEquals("id", 1, user);  //断言user的id属性的值是1 
assertPropertyLenEquals("address.street", "First street", user); //断言user的address的street属性

      在这个方式中你期望的值和判定的对象也可以使用集合

assertPropertyLenEquals("id", Arrays.asList(1, 2, 3), users);
assertPropertyLenEquals("address.street", Arrays.asList("First street", 
"Second street", "Third street"), users);
posted on 2008-04-05 14:23 小小~咖啡豆 阅读(2301) 评论(5)  编辑  收藏 所属分类: 测试

FeedBack:
# re: Unitils开发指南(一) 2009-04-14 16:42 skyme
assertRefEquals()这个方法好像是有问题的:
我调试的时候用ReflectionAssert.assertRefEquals(user1, user2);

import org.unitils.reflectionassert.*;
import org.unitils.reflectionassert.ReflectionAssert;
public void testUser(){
User user1=new User(1,"John","Doe");
User user2=new User(1,"John","Doe");
ReflectionAssert.assertRefEquals(user1, user2);
}
测试是不通过的!
如果我不要ReflectionAssert;那么报错
按上面的代码测试,测试不通过。好像这个反射是不是有问题啊!  回复  更多评论
  
# re: Unitils开发指南(一) 2009-04-14 21:39 wangzhouyu
有验证通过呀,@skyme
  回复  更多评论
  
# re: Unitils开发指南(一) 2009-04-15 09:03 skyme
使用Myeclipse6.0吗? 我在看看我的测试环境JUnit3还是JUnit4
我用的是Unitils2.2.jar包  回复  更多评论
  
# re: Unitils开发指南(一) 2009-04-15 09:37 skyme
请问下能不能告诉我你的msn,我的msn是:jiangduxi@yahoo.com.cn!
想向你请教下! 谢谢  回复  更多评论
  
# re: Unitils开发指南(一) 2009-04-15 10:17 wangzhouyu
wzywjy@hotmail.com
  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: