我必须测试一个用spring注入两个映射的类。我想模拟这两张地图。我使用模拟符号如下:
@Mock
private Map<String, Integer> map1;
@Mock
private Map<String, Date> map2;
但我得到以下错误:
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.util.Date
两个地图似乎都只使用了第一个模拟地图。
我做错了什么?
只要两个字段的类型相同,mockito
就不知道如何按类型注入mock。所以它尝试按名称注入。在这种情况下,测试中的类中的字段名称似乎与您创建的mock对象不匹配。这是@InjectMocks
:的文档
字段注入;mock将首先按类型解析(如果无论名称如何,类型匹配注入都会发生),然后,如果根据字段的匹配情况,存在几个相同类型的属性name和模拟名称。
您可以重命名您的文件或使用显式模拟名称:
@Mock(name="foo")
private Map<String, Integer> map1;
@Mock(name="bar")
private Map<String, Date> map2;
但我不认为这是最好的解决方案。如果文件名将被重命名,您将得到假阴性的测试结果:功能正常,但测试失败。
对我来说,最好的解决方案是重构代码,以便被测试的类在构造函数中接收依赖项。之后你可以这样嘲笑它:
@Mock
private Map<String, Integer> map1;
@Mock
private Map<String, Date> map2;
private ClassUnderTets cut;
@Before
public void setUp() throws Exception {
cut = new ClassUnderTets(map1, map2);
}
甚至:
@Mock
private Map<String, Integer> map1;
@Mock
private Map<String, Date> map2;
@InjectMocks
private ClassUnderTets cut;
如文件中所述:
构造函数注入;选择最大的构造函数,然后用仅在测试中声明的模拟
可能您遇到了问题,因为您试图用相同的接口注入两个mock(例如,变量名称与属性不匹配)
请看一下这个主题的第二篇文章以供参考。
属性设置器注入;mock将首先按类型解析,如果存在多个相同类型的属性,则通过属性名称和模拟名称。
尝试
@Mock
private Map map1;
@Mock
private Map map2;
而是
@Mock
private Map<String, Integer> map1;
@Mock
private Map<String, Date> map2;
然后你只需要模仿一种行为,比如:
when(map1).get("hello").thenReturn(25);
when(map2).get("birthday").thenReturn(new Date(2000, 07, 24));