Java Mockito日期格式返回的月份不正确;assertEquals失败
我正在尝试使用mockito模拟DateFormat。我只想显示当前月份。在Junit测试中,我在Junit测试中执行以下操作:Java Mockito日期格式返回的月份不正确;assertEquals失败,java,exception,junit,mockito,simpledateformat,Java,Exception,Junit,Mockito,Simpledateformat,我正在尝试使用mockito模拟DateFormat。我只想显示当前月份。在Junit测试中,我在Junit测试中执行以下操作: @Before public void setUp() throws Exception { reportQueryParams = ReportQueryParams.builder() .id("07") .build(); } @Test public void tabSerializerTest() { Da
@Before
public void setUp() throws Exception {
reportQueryParams = ReportQueryParams.builder()
.id("07")
.build();
}
@Test
public void tabSerializerTest() {
DateFormat formatter = Mockito.mock(SimpleDateFormat.class);
StringBuffer stringBuffer = new StringBuffer("July");
Mockito.when(formatter.format(Mockito.any(Date.class), Mockito.any(StringBuffer.class),
Mockito.any(FieldPosition.class))).thenReturn(stringBuffer);
MetricsSerializer metricsSerializer = new MetricsSerializer();
String tabSeparated = metricsSerializer.serializeMetrics(reportQueryParams);
String expected = new StringBuilder().append("074")
.append("\t")
.append("July")
.toString();
assertEquals(expected, tabSeparated);
}
我正在测试的功能:
public String serializeMetrics(final ReportQueryParams reportQueryParams) {
stringJoiner = new StringJoiner("\t");
addValueFromString(reportQueryParams.getId());
addValueFromString(getCurrentMonth());
return stringJoiner.toString();
}
private String getCurrentMonth() {
DateFormat monthFormat = new SimpleDateFormat("MMMMM");
return monthFormat.format(new Date());
}
private void addValueFromString(final String value) {
stringJoiner.add(value);
}
我的ReportQueryParams类:
public class ReportQueryParams {
private String id;
}
我得到了“八月”作为从功能返回的月份。因此,assertEquals正在失败。如何解决这个问题?这里的问题是,在任何时候,模拟都不会在被测试的类中结束,因此不会调用安排的行为 这是因为您正在使用测试中的方法创建格式化程序
DateFormat monthFormat = new SimpleDateFormat("MMMMM");
将类与依赖项紧密耦合,这使得测试很困难,但并非不可能
不幸的是,PowerMockito允许这样的事情
SimpleDateFormat formatter = mock(SimpleDateFormat.class);
when(formatter.format(any(Date.class)).thenReturn("July");
PowerMockito.whenNew(SimpleDateFormat.class).withArguments(anyString()).thenReturn(formatter);
//...Do not forget to include @PrepareForTest(SimpleDateFormat.class) on the test class
理想情况下,您应该做的是重构类,以通过构造或方法参数公开任何可以注入测试主题的显式依赖项
public interface MonthProvider {
private String getCurrentMonth();
}
public class DefaultMonthProvider implements MonthProvider {
DateFormat monthFormat = new SimpleDateFormat("MMMMM");
public String getCurrentMonth() {
return monthFormat.format(new Date());
}
}
public class MetricsSerializer {
MonthProvider provider;
public MetricsSerializer(MonthProvider provider) {
this.provider = provider;
}
public String serializeMetrics(final ReportQueryParams reportQueryParams) {
stringJoiner = new StringJoiner("\t");
addValueFromString(reportQueryParams.getId());
addValueFromString(provider.getCurrentMonth());
return stringJoiner.toString();
}
private void addValueFromString(final String value) {
stringJoiner.add(value);
}
}
@Before
public void setUp() throws Exception {
reportQueryParams = ReportQueryParams.builder()
.id("07")
.build();
}
@Test
public void tabSerializerTest() {
//Arrange
MonthProvider privider = Mockito.mock(MonthProvider.class);
Mockito.when(provider.getCurrentMonth()).thenReturn("July");
MetricsSerializer metricsSerializer = new MetricsSerializer(provider);
String expected = new StringBuilder().append("07")
.append("\t")
.append("July")
.toString();
//Act
String actual = metricsSerializer.serializeMetrics(reportQueryParams);
//Assert
assertEquals(expected, actual);
}
可以注射到受试者体内
public interface MonthProvider {
private String getCurrentMonth();
}
public class DefaultMonthProvider implements MonthProvider {
DateFormat monthFormat = new SimpleDateFormat("MMMMM");
public String getCurrentMonth() {
return monthFormat.format(new Date());
}
}
public class MetricsSerializer {
MonthProvider provider;
public MetricsSerializer(MonthProvider provider) {
this.provider = provider;
}
public String serializeMetrics(final ReportQueryParams reportQueryParams) {
stringJoiner = new StringJoiner("\t");
addValueFromString(reportQueryParams.getId());
addValueFromString(provider.getCurrentMonth());
return stringJoiner.toString();
}
private void addValueFromString(final String value) {
stringJoiner.add(value);
}
}
@Before
public void setUp() throws Exception {
reportQueryParams = ReportQueryParams.builder()
.id("07")
.build();
}
@Test
public void tabSerializerTest() {
//Arrange
MonthProvider privider = Mockito.mock(MonthProvider.class);
Mockito.when(provider.getCurrentMonth()).thenReturn("July");
MetricsSerializer metricsSerializer = new MetricsSerializer(provider);
String expected = new StringBuilder().append("07")
.append("\t")
.append("July")
.toString();
//Act
String actual = metricsSerializer.serializeMetrics(reportQueryParams);
//Assert
assertEquals(expected, actual);
}
更改参数匹配器,还需要在手动创建实例时重构代码以注入类?您能提供一个例子吗?您需要提供更多关于正在测试的内容的详细信息,以及如何在一个可用于重现问题的环境中测试它。我只是使用“getCurrentMonth()”函数获取当前月份。在测试中,我试图模拟这种行为并提供月份。对不起,您应该首先阅读您打算使用的工具的文档。嘲笑是复杂的事情。你不能通过反复试验来了解这一点。你从一个好的教程开始,然后自上而下地学习
Mockito.when(formatter.format(new Date())
错误时,需要类似于Mockito.when(formatter.format(any())
(其中any是参数匹配器)有没有一种方法可以不使用PowerMockito就可以做到这一点?@TeeJay没有重构subject类中的格式化程序,以便可以注入模拟。格式化程序应该从类或方法“getCurrentMonth()中删除?@TeeJaygetCurrentMonth
将是从subject类中抽象出来的更好选择,因为SimpleDataFormat
更像是一个实现concernI尝试过的MetricsSerializer mockMonth=mock(MetricsSerializer.class);when(mockMonth.getCurrentMonth())。然后返回(“七月”);但这也给了八月。