无障碍assertEquals(Object obj1,Object obj2),想怎么比较就怎么比较!! [ 光影人像 东海陈光剑 的博客 ]
- l 第一种相等(==):两个句柄(或叫引用)指向了同一个对象;即obj1==obj2为true
- l 第二种相等(equal):两个对象里包含的成员属性对应相等;
public boolean equals(Object obj) {
return (this == obj);
} 一般自定义的类,为使equals()方法名副其实,都需要对它进行重写。 在举例子先介绍下例子中几个JavaBean的关系:![e69caae591bde5908d](http://rdc.taobao.com/blog/qa/wp-content/uploads/2009/02/e69caae591bde5908d.bmp)
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final POJO other = (POJO) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (owner == null) {
if (other.owner != null)
return false;
} else if (!owner.equals(other.owner))
return false;
if (pic == null) {
if (other.pic != null)
return false;
} else if (!pic.equals(other.pic))
return false;
if (title == null) {
if (other.title != null)
return false;
} else if (!title.equals(other.title))
return false;
if (url == null) {
if (other.url != null)
return false;
} else if (!url.equals(other.url))
return false;
return true;
}
当然POJO中的owner为User对象,User对象的equals()方法也要重写。
Item继承自POJO,其equals()重写可以如下:@Override
public boolean equals(Object obj) {
if(!super.equals(obj))
return false;
if(!(obj instanceof Item))
return false;
Item that = (Item)obj;
if(this.currPrice == null && that.currPrice == null)
// 注意这里一定是this.XX.equals(that.XX)[因为使用了短路与&&],以免出现
// NullPointerException
if(this.remainTime == null && that.remainTime == null
||this.remainTime.equals(that.remainTime))
return true;
if(this.remainTime == null && that.remainTime == null
&& this.currPrice.equals(that.currPrice))
return true;
if(this.currPrice.equals(that.currPrice)
&& this.remainTime.equals(that.remainTime))
return true;
return false;
} 当然也可以方便的使用代码自动生成:@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
final Item other = (Item) obj;
if (currPrice == null) {
if (other.currPrice != null)
return false;
} else if (!currPrice.equals(other.currPrice))
return false;
if (remainTime == null) {
if (other.remainTime != null)
return false;
} else if (!remainTime.equals(other.remainTime))
return false;
return true;
} 于是:@Test
public void testItemEqual() {
Item item1 = new Item(2l,new User(1l,"pwd","name"),"title","pic","url",
15.0f,new Date());
Item item2 = new Item(2l,new User(1l,"pwd","name"),"title","pic","url",
15.0f,new Date());
// 一句assertEquals搞定assertEquals(item1, item2);
} 这样看来似乎价值还不是很大,再来看ItemList比较,顺便介绍下Comparator接口:public void testItemListEqualV2() {
List<Item> itemList1 = new ArrayList<Item>();
List<Item> itemList2 = new ArrayList<Item>();
for(int i=0;i<10;i++)
itemList1.add(new Item((long)i,new User((long)i,"pwd","name"),
"title","pic","url",15.0f,new Date()));
for(int i=9;i>=0;i--)
itemList2.add(new Item((long)i,new User((long)i,"pwd","name"),
"title","pic","url",15.0f,new Date()));
int size = itemList1.size();
// 以上准备数据,可以略过
// 开始比较
assertEquals(size, itemList2.size());
Item[] itemArray1 = new Item[size];
Item[] itemArray2 = new Item[size];
Arrays.sort((Item[])itemList1.toArray(itemArray1), new ItemComparator());
Arrays.sort((Item[])itemList2.toArray(itemArray2), new ItemComparator());
for(int j =0 ; j<size;j++){
assertEquals(itemArray1[j],itemArray2[j]);
}
}
class ItemComparator implements Comparator<Item>{
public int compare(Item item1, Item item2) {
if(item1.getId() < item2.getId())
return -1;
else if(item1.getId() > item2.getId())
return 1;
else
return 0;
}
} 思路就是将期望list和实际list进行排序后逐个比较,这里明显有一个好处,可以明确的知道list中哪个位置的对象assertEquals() 失败。 到此结束了吗?看也没有什么多大好处,重写equals()照样费事? 当然不是!第三种相等!想怎么比较就怎么比较!! 往往开发并不会给我们重写好equals(),当然测试也不能随便改开发的代码。 看我怎么比较没有重写equals()的Blog对象,又是代码:@Test
public void testBlogEqual() {
Blog blog1 = new Blog(4l,new User(1l,"pwd","name"),
"title","pic","url","description"){
@Override
public boolean equals(Object obj){
if(super.equals(obj)){
if(obj instanceof Blog){
Blog that = (Blog)obj;
if(this.getDescription() == null
&& that.getDescription() == null)
return true;
if(this.getDescription().equals(that.getDescription()))
return true;
}
}
return false;
}
};
Blog blog2 = new MockBlog(4l,new User(1l,"pwd","name"),
"title","pic","url","description");
Blog blog3 = new Blog(4l,new User(1l,"pwd","name"),
"title","pic","url","description");
Blog blog4 = new Blog(4l,new User(1l,"pwd","name"),
"title","pic","url","description4");
assertEquals(blog1, blog3); // success
assertEquals(blog2, blog3); // success
assertEquals(blog1, blog4); // fail
assertEquals(blog2, blog4); // fail
assertEquals(blog4, blog1); // success,原因是Blog的超类POJO重写了equals()
assertEquals(blog4, blog2); // success
}
class MockBlog extends Blog{
public MockBlog() {
super();
}
public MockBlog(Long id, User user, String title, String pic,
String url, String description) {
super(id, user, title, pic, url, description);
}
public MockBlog(Long id, User user) {
super(id, user);
}
@Override
public boolean equals(Object obj){
if(super.equals(obj)){
// 注意这里一定是查看是否Blog的实例
if(obj instanceof Blog){
Blog that = (Blog)obj;
if(this.getDescription() == null
&& that.getDescription() == null)
return true;
if(this.getDescription().equals(that.getDescription()))
return true;
}
}
return false;
}
}
说明一下:测试方法testBlogEqual()中blog1、blog2、blog3里面各个成员的值都相等(equal)、blog4的description不同。blog1和blog2都是Blog子类的实例,只不过blog1是Blog匿名子类的实例。可以看到几个assertEquals()的结果如注释。其中需要说明的是:
看Assert.assertEquals()源码
static public void assertEquals(String message, Object expected, Object actual) {
if (expected == null && actual == null)
return;
if (expected != null && expected.equals(actual))
return;
failNotEquals(message, expected, actual);
} 这里可以看出assertEquals()实际调用的是expected对象的equals方法,所以只管对期望对象进行mock! 于是再举个例子:Shop(id,owner,title,pic,url,buyNo),只想要比较id和buyNo@Test
public void testShopEqual() {
Shop shop1 = new Shop(1l,new User(1l,"pwd","name"),"title","pic1","url1",20l){
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj instanceof POJO) {
POJO other = (POJO) obj;
if (id == null) {
if (other.getId() != null)
return false;
} else if (!id.equals(other.getId()))
return false;
}
if (!(obj instanceof Shop))
return false;
final Shop other = (Shop) obj;
if (this.getBuyerNo() == null) {
if (other.getBuyerNo() != null)
return false;
} else if (!this.getBuyerNo().equals(other.getBuyerNo()))
return false;
return true;
}
};
Shop shop2 = new Shop(1l,new User(1l,"pwd","name"),"title","pic2","url2",20l);
assertEquals(shop1, shop2);
} assertEquals()通过。 以上因为Shop又继承POJO,所以equals()重写得有些复杂,一般JavaBean都直接继承Object,就没有这么复杂了。 为了重用新写的equals()方法,可以将你名字类mock为一个内部类(外部类当然也可以)。 再举一例:常常在进行数据库校验之前需要assertNotNull(),以User为例@Test
public void testUserNotNull() {
User user1 = new User(){
@Override
public boolean equals(Object obj) {
if((obj instanceof User)){
User that = (User)obj;
if(that.getId()!=null && that.getName()!=null && that.getPassword()!=null)
return true;
}
return false;
}
};
User user2 = new User(1l,"pwd","name");
assertEquals(user1, user2);
} 再结合Debug工具,也很快就能定位到哪个属性值为null。 That all , enjoy!我们从来只做一件事,分享.
让美在这个世界流转
让倍感无趣的 受伤的 彷徨的 孤独的 或是心情忧郁的 人生黯淡的人们
能有一次机会
去再一次发现这个世界的美
并把美传递给他人
---光影人像(Follow WeChat public number with interest)