如何用可变数据初始化 Mock
我有这个方法要测试:
public static Date getDateSinceUTC(CstOrderBean orderBean) {
int year = orderBean.getDeadLineYear();
int month = orderBean.getDeadLineMonth();
int day = orderBean.getDeadLineDay();
int hour = orderBean.getDeadLineHour();
int minute = orderBean.getDeadLineMinute();
String ap = orderBean.getDeadLineAmPm() == 1 ? "PM" : "AM";
//TODO AM=0, PM=1 comes from html form
SimpleDateFormat df = new SimpleDateFormat("yyyy:MM:dd:hh:mm:aa");
String stringDate = stringifyIntegers(":", year, month, day, hour, minute);
stringDate = stringDate.concat(ap);
Date date;
try {
date = df.parse(stringDate);
} catch (ParseException e) {
throw new Error("Parsing date from html form failed", e);
}
return date;
}
其中 CstOrderBean 需要由 Mockito 模拟,因为它不是 POJO(一些静态初始化等 - 来自源代码生成器)。但我需要运行该方法 xxx 次,因此使用许多数据组合设置模拟
,我可以使用 TestNG 的 @DataProvider 来做到这一点。但我不知道该怎么做,我想:
when(ob.getDeadLineYear()).thenReturn(1, 2, 3);
....
循环是一个坏主意,不是吗?创建 xx 模拟并像这样初始化它们的正确方法是吗?
I have this method to test :
public static Date getDateSinceUTC(CstOrderBean orderBean) {
int year = orderBean.getDeadLineYear();
int month = orderBean.getDeadLineMonth();
int day = orderBean.getDeadLineDay();
int hour = orderBean.getDeadLineHour();
int minute = orderBean.getDeadLineMinute();
String ap = orderBean.getDeadLineAmPm() == 1 ? "PM" : "AM";
//TODO AM=0, PM=1 comes from html form
SimpleDateFormat df = new SimpleDateFormat("yyyy:MM:dd:hh:mm:aa");
String stringDate = stringifyIntegers(":", year, month, day, hour, minute);
stringDate = stringDate.concat(ap);
Date date;
try {
date = df.parse(stringDate);
} catch (ParseException e) {
throw new Error("Parsing date from html form failed", e);
}
return date;
}
Where CstOrderBean needs to be mocked by Mockito because it is not a POJO (some static initializations etc. - from source code generator). But I need to run the method xxx times, hence set the mocks with many data combinations
I could use TestNG's @DataProvider to do that. But I'm not sure how to do that, I guess that :
when(ob.getDeadLineYear()).thenReturn(1, 2, 3);
....
in loop is a bad idea, isn't it ? Is the correct way of doing this to create xx mocks and initialize them like that ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
每个测试都应该有自己的模拟,最好没有可变数据。如果您使用同一模拟对象的多个不同返回值,则测试必须是白盒测试,因为测试与对模拟方法的调用次数而不是被测试方法的结果相结合。
也就是说,您可以通过重复调用 thenReturn 或将返回值定义为 varargs 来定义一组返回值。
这可能更清晰,因为您应该控制模拟返回的值。
Each test should get their own mock that preferably does not have variable data. If you use several different return values from the same mock object then the testing has to be white-box testing as the test is coupled with the number of calls to a mocked method instead of the result of the method under test.
That said, you are able to define a set of return values with calling thenReturn repeatedly or by defining the return values as varargs
This might be cleaner as you should probably control the values that the mock returns anyway.
如何模拟取决于您想要测试的内容。在截止日期年份循环可能无法完成您想要的工作。
用于查看闰年是否有效的一个测试可能类似于:(
警告:以上代码是手动输入的)。混合、匹配并重复您需要测试的其他日期以验证 getDateSinceUTC 是否正常工作。您可能需要一个单独的测试方法来检查无效日期,例如 2/30/2012(并期望抛出异常)。您可能想要检查无效时间,例如 23:61。您可能需要检查有效日期,例如您的生日。
请查看“正常”情况、边界情况和错误情况,而不是年份循环。这是单元测试的更好实践。
How you mock depends on what you would like to test. Looping on the deadline year might not do the job you want it to.
One test for seeing if a leap year works might be something like:
(Warning: above codes was typed in by hand). Mix, match, and repeat for other dates that you need to test to verify that getDateSinceUTC is working. You might want a separate test method to check invalid dates, like 2/30/2012 (and expect a throw). You might want to check invalid times like 23:61. You might want to check valid dates, like your birthdate.
Instead of a loop on the year, please look at "normal" cases, borderline cases, and error cases. This is the better practice for unit testing.