Junit - 断言两个相同的数组列表会使测试失败
Junit - Asserting two identical arraylists makes test fail
我正在对一个端点进行测试。这个端点 returns 一个对象列表,所以我的测试包括与数组列表进行比较。测试已经在第一个元素中失败,即使日志显示对象的字段相同:
org.opentest4j.AssertionFailedError:可迭代内容在索引 [0] 处不同,预期: 但是是:<{dispatchNumber=1, creationDate=null, pickUpDate=null, completionDate=null, estimatedDate=null, deliverymanName=edgar, receiverName= null, receiverTlfNumber=null, status=null}>
测试代码如下:
@Test
void whenFindByUser(){
Dispatch disp1 = new Dispatch();
disp1.setDispatchNumber(1);
disp1.setDeliverymanName("edgar");
Dispatch disp2 = new Dispatch();
disp2.setDispatchNumber(2);
disp2.setDeliverymanName("paola");
Dispatch disp3 = new Dispatch();
disp3.setDispatchNumber(3);
disp3.setDeliverymanName("marco");
List<Dispatch> dummyDispatches = new ArrayList<Dispatch>(Arrays.asList(disp1, disp2, disp3));
when(service.findByUser("123")).thenReturn(dummyDispatches);
List<Dispatch> realDispatches = restClient.getForObject(localhost + port + "/find/user/123", dummyDispatches.getClass());
//assertArrayEquals(dummyDispatches.toArray(), realDispatches.toArray());
//assertEquals(dummyDispatches.get(1), realDispatches.get(1));
assertIterableEquals(dummyDispatches, realDispatches);
}
测试结束时注释的功能是我采用的其他方法使其工作,但没有用。
再看看错误信息。比较两个值:
<Dispatch(dispatchNumber=1, creationDate=null, pickUpDate=null, completionDate=null, estimatedDate=null, deliverymanName=edgar, receiverName=null, receiverTlfNumber=null, status=null)>
<{dispatchNumber=1, creationDate=null, pickUpDate=null, completionDate=null, estimatedDate=null, deliverymanName=edgar, receiverName=null, receiverTlfNumber=null, status=null}>
如果它们相等,那么这 2 个值看起来应该完全相同,但实际上并非如此。
第一个有 Dispatch(...)
,第二个有 {...}
.
这是为什么?好吧,首先是在 Dispatch
class 上调用 toString()
的结果。第二个不是,不可能,那是什么?
如果我们回头看看第二个来自哪里,我们会发现:
List<Dispatch> realDispatches = restClient.getForObject(..., dummyDispatches.getClass());
问题在于,由于 type erasure,dummyDispatches.getClass()
与 List.class
相同,即该方法仅被告知解析为List
,但不是列表中应包含何种对象。
在不知道对象种类的情况下,它解析为 Map<String, Object>
,它适合第二个值的输出,即 {name=value, ...}
.
但是,你接着说,return 值被声明为 List<Dispatch>
,而不是 List<Map<String, Object>>
,那么我们为什么不报错呢?
因为 List.class
是 raw 类型,使得 return 值声明为 raw List<Map>
,并且是 raw,出于向后兼容的原因,它默默地被认为与 List<Map<ANYTHING>>
赋值兼容。
在 IDE 中,您可以启用编译器警告来提醒您注意此类问题。
解决方案:改为使用数组,因为数组组件类型在运行时保留:
Dispatch[] realDispatches = restClient.getForObject(..., Dispatch[].class);
这当然会影响您的 assert
调用,但您可以使用 Arrays.asList(...)
.
转换为列表
我正在对一个端点进行测试。这个端点 returns 一个对象列表,所以我的测试包括与数组列表进行比较。测试已经在第一个元素中失败,即使日志显示对象的字段相同:
org.opentest4j.AssertionFailedError:可迭代内容在索引 [0] 处不同,预期:
测试代码如下:
@Test
void whenFindByUser(){
Dispatch disp1 = new Dispatch();
disp1.setDispatchNumber(1);
disp1.setDeliverymanName("edgar");
Dispatch disp2 = new Dispatch();
disp2.setDispatchNumber(2);
disp2.setDeliverymanName("paola");
Dispatch disp3 = new Dispatch();
disp3.setDispatchNumber(3);
disp3.setDeliverymanName("marco");
List<Dispatch> dummyDispatches = new ArrayList<Dispatch>(Arrays.asList(disp1, disp2, disp3));
when(service.findByUser("123")).thenReturn(dummyDispatches);
List<Dispatch> realDispatches = restClient.getForObject(localhost + port + "/find/user/123", dummyDispatches.getClass());
//assertArrayEquals(dummyDispatches.toArray(), realDispatches.toArray());
//assertEquals(dummyDispatches.get(1), realDispatches.get(1));
assertIterableEquals(dummyDispatches, realDispatches);
}
测试结束时注释的功能是我采用的其他方法使其工作,但没有用。
再看看错误信息。比较两个值:
<Dispatch(dispatchNumber=1, creationDate=null, pickUpDate=null, completionDate=null, estimatedDate=null, deliverymanName=edgar, receiverName=null, receiverTlfNumber=null, status=null)>
<{dispatchNumber=1, creationDate=null, pickUpDate=null, completionDate=null, estimatedDate=null, deliverymanName=edgar, receiverName=null, receiverTlfNumber=null, status=null}>
如果它们相等,那么这 2 个值看起来应该完全相同,但实际上并非如此。
第一个有 Dispatch(...)
,第二个有 {...}
.
这是为什么?好吧,首先是在 Dispatch
class 上调用 toString()
的结果。第二个不是,不可能,那是什么?
如果我们回头看看第二个来自哪里,我们会发现:
List<Dispatch> realDispatches = restClient.getForObject(..., dummyDispatches.getClass());
问题在于,由于 type erasure,dummyDispatches.getClass()
与 List.class
相同,即该方法仅被告知解析为List
,但不是列表中应包含何种对象。
在不知道对象种类的情况下,它解析为 Map<String, Object>
,它适合第二个值的输出,即 {name=value, ...}
.
但是,你接着说,return 值被声明为 List<Dispatch>
,而不是 List<Map<String, Object>>
,那么我们为什么不报错呢?
因为 List.class
是 raw 类型,使得 return 值声明为 raw List<Map>
,并且是 raw,出于向后兼容的原因,它默默地被认为与 List<Map<ANYTHING>>
赋值兼容。
在 IDE 中,您可以启用编译器警告来提醒您注意此类问题。
解决方案:改为使用数组,因为数组组件类型在运行时保留:
Dispatch[] realDispatches = restClient.getForObject(..., Dispatch[].class);
这当然会影响您的 assert
调用,但您可以使用 Arrays.asList(...)
.