我目前正在使用JMockito / PowerMock,以便我可以模拟静态方法的返回值,在本例中为Calendar.getInstance()。 我的问题与此非常相似,但并不完全如此: PowerMocking static does not return expected object
我还检查了其他各种类似的主题,但没有一个完全属于我的背景。目前,我有一个像这样的代码:
Calendar cal = Calendar.getInstance();
//modifies this instance
.....
.....
//then there is another call:
cal2 = Calendar.getInstance();
....
....
逻辑的作用在这里并不重要。当我尝试测试这个方法块时,我的期望是这样的:
Calendar myOwn = //whatever
when(Calendar.getInstance()).thenReturn(myOwn);
因此在测试期间测试的结果是,在Calendar.getInstance()
的第一次调用中,它设法成功获得myOwn
对象,这正是我所期望的。显然,该方法然后对此对象进行了一些修改。
然而,在调试时,当下一次调用Calendar.getInstance()
发生时,变量cal2
似乎从之前获得myOwn
对象的修改版本。我原本以为它会获得原始的 myOwn
日历对象,但它没有。
我也尝试重建对此的期望(因为总共有两个getInstance()
调用,至少在此方法中):
when(Calendar.getInstance()).thenReturn(myOwn).theReturn(myOwn);
但没有运气。然后我想是否这是一个变量通过引用传递的问题,因为它是静态的,但是,以下输出是有效的,并且完全合乎逻辑,因为我单独测试它。
Calendar cal = Calendar.getInstance();
System.out.println(cal.getTime()); //prints current date object (as expected)
cal.set(Calendar.YEAR, 2017);
System.out.println(cal.getTime()); //prints modified timestamp of 2017 (as expected)
//new instance
Calendar cal2 = Calendar.getInstance();
System.out.println(cal2.getTime()); //still prints current date object (as expected)
如果我在修改之前克隆了之前代码中的第二个日历对象实例,我可以轻松修复我的测试。但这涉及修改现有的源代码,因为它是一个非常遗留的代码。
那么在我使用这种静态方法进行单元测试时,我做错了什么?我也试过用JMockit进行测试,但仍然遇到同样的问题。很确定它是显而易见的东西,但无法弄清楚。谢谢你的时间。
答案 0 :(得分:1)
那是因为myOwn
是同一个实例。 thenReturn
代码仅在测试开始时运行一次。您只创建了一个Calendar
对象,而Mockito只是将其返回两次。因此,如果在第一次调用getInstance
时对其进行了修改,则该修改后的对象将在第二次被调用时返回。
尝试改为:
Calendar myOwn = //whatever
Calendar myOwnSecond = //whatever - new instance though, not the same as myOwn!!
when(Calendar.getInstance()).thenReturn(myOwn).thenReturn(myOwnSecond);
如果您希望每次都返回一个新的日历实例(因此,当您需要x
个日历实例数时),并且您不需要为测试保留日历实例,您将要使用thenAnswer
。查看here了解详细信息。或者只使用:
when(Calendar.getInstance()).thenAnswer((invocation)->new MyCalendar());
或Java 7
when(Calendar.getInstance())
.thenAnswer(new Answer<Calendar>() {
Calendar answer(InvocationOnMock invocation) {
return // however you're instantiating it
}
});