如何模拟在另一个 class 中使用另一个静态最终变量的变量
How to mock a variable that uses another static final variable in another class
我在 junit 中设置此待测方法时遇到问题。我正在尝试使用新的时间戳测试 updateConfigDates 的方法。请耐心等待,因为提供了很多信息,而且看起来不太漂亮。
这里是正在测试的方法
public static Document updateConfigDates(Document doc, Timestamp configDate)
{
//Format timestamp to string
String configTimestampStr = GTR_DATE_FORMAT.format(configDate) + "Z";
//Change configuration date for all nodes in GTR
NodeList configIDNodes = doc.getElementsByTagName("ConfigDate");
for (Element cidNode : new DOMUtil.ElementList(configIDNodes))
{
cidNode.setTextContent(configTimestampStr);
}
return doc;
}
问题在线:
//Format timestamp to string
String configTimestampStr = GTR_DATE_FORMAT.format(configDate) + "Z";
它正在使用 public final class 常量
public final class Constants
{
/** GTR Timestamp formatter without micro-second */
public static final FastDateFormat GTR_DATE_FORMAT
= FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss");
}
这是我当前的测试用例
@Test
public void testUpdateConfigDates() throws Exception
{
// check if configDate in document is expected
String docConfigDate = doc.getElementsByTagName("ConfigDate").item(0).getTextContent();
assertEquals(docConfigDate, "2012-02-22T16:07:27Z");
LOG.info("docConfigDate: " + docConfigDate);
// variables
Timestamp newConfigDate = Timestamp.valueOf("2009-07-29 13:24:11");
// Mocking statics
//PowerMockito.mockStatic(GTRConstants.class);
// String configTimestampStr = GTR_DATE_FORMAT.format(configDate) + "Z";
//common.setFinalStatic(GTRUtility.class.getDeclaredField("configTimestampStr"), "yyyy-MM-dd'T'HH:mm:ss" + "Z");
common.setFinalStatic(Constants.class.getDeclaredField("GTR_DATE_FORMAT"), FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss"));
/* setFinalStatic ExceptionInInitializerError information below
*
* Field#set(Object, Object) can be used to set static fields.
* If you try to set the field of an uninitialized class, the JVM will first try to initialize the class.
* If a failure occurs, then set will throw a ExceptionInInitializerError.
*/
// execute method under test
doc = gtrUtility.updateConfigDates(doc, newConfigDate);
// verify expectations
docConfigDate = doc.getElementsByTagName("ConfigDate").item(0).getTextContent();
assertEquals(docConfigDate, "2009-07-29 13:24:11");
}
使用 setFinalStatic solution posted here,它成功地与我正在做的一些其他测试一起工作。
public static void setFinalStatic(Field field, Object newValue) throws Exception
{
field.setAccessible(true);
// remove final modifier from field
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, newValue);
}
我试过几种方案:
- 我最近的新方法,使用 setFinalStatic method
- PowerMockito 和 Mockito 的模拟常量结果。
- 使用 PowerMockito 和 Mockito 模拟 GTR_DATE_FORMAT 实例。
- 使用 PowerMockito 和 Mockito 模拟 FastDateFormat。
全部失败。我认为 setFinalStatic 方法是最接近的,但是我目前收到错误 ExceptionInInitializerError(正如用户 here and in Oracle Doc here 所讨论的那样)
事实证明,我的问题的答案是常量文件正在执行一些我必须模拟的初始化方法(在本例中:来自数据库的对象上的 safeGetTypeId(x))。
当我意识到 updateObjectId 硬编码测试正在运行并且 updateTimestamp 使用常量 class GTR_DATE_FORMAT.
时,我应该更快地注意到这一点
构造函数是空的,我不希望执行任何其他内容。
这是一个极端复杂的问题,所以我可能会删除这个问题,但是如果它对以后的人有帮助,我会留下它。
我在 junit 中设置此待测方法时遇到问题。我正在尝试使用新的时间戳测试 updateConfigDates 的方法。请耐心等待,因为提供了很多信息,而且看起来不太漂亮。
这里是正在测试的方法
public static Document updateConfigDates(Document doc, Timestamp configDate)
{
//Format timestamp to string
String configTimestampStr = GTR_DATE_FORMAT.format(configDate) + "Z";
//Change configuration date for all nodes in GTR
NodeList configIDNodes = doc.getElementsByTagName("ConfigDate");
for (Element cidNode : new DOMUtil.ElementList(configIDNodes))
{
cidNode.setTextContent(configTimestampStr);
}
return doc;
}
问题在线:
//Format timestamp to string
String configTimestampStr = GTR_DATE_FORMAT.format(configDate) + "Z";
它正在使用 public final class 常量
public final class Constants
{
/** GTR Timestamp formatter without micro-second */
public static final FastDateFormat GTR_DATE_FORMAT
= FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss");
}
这是我当前的测试用例
@Test
public void testUpdateConfigDates() throws Exception
{
// check if configDate in document is expected
String docConfigDate = doc.getElementsByTagName("ConfigDate").item(0).getTextContent();
assertEquals(docConfigDate, "2012-02-22T16:07:27Z");
LOG.info("docConfigDate: " + docConfigDate);
// variables
Timestamp newConfigDate = Timestamp.valueOf("2009-07-29 13:24:11");
// Mocking statics
//PowerMockito.mockStatic(GTRConstants.class);
// String configTimestampStr = GTR_DATE_FORMAT.format(configDate) + "Z";
//common.setFinalStatic(GTRUtility.class.getDeclaredField("configTimestampStr"), "yyyy-MM-dd'T'HH:mm:ss" + "Z");
common.setFinalStatic(Constants.class.getDeclaredField("GTR_DATE_FORMAT"), FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss"));
/* setFinalStatic ExceptionInInitializerError information below
*
* Field#set(Object, Object) can be used to set static fields.
* If you try to set the field of an uninitialized class, the JVM will first try to initialize the class.
* If a failure occurs, then set will throw a ExceptionInInitializerError.
*/
// execute method under test
doc = gtrUtility.updateConfigDates(doc, newConfigDate);
// verify expectations
docConfigDate = doc.getElementsByTagName("ConfigDate").item(0).getTextContent();
assertEquals(docConfigDate, "2009-07-29 13:24:11");
}
使用 setFinalStatic solution posted here,它成功地与我正在做的一些其他测试一起工作。
public static void setFinalStatic(Field field, Object newValue) throws Exception
{
field.setAccessible(true);
// remove final modifier from field
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, newValue);
}
我试过几种方案:
- 我最近的新方法,使用 setFinalStatic method
- PowerMockito 和 Mockito 的模拟常量结果。
- 使用 PowerMockito 和 Mockito 模拟 GTR_DATE_FORMAT 实例。
- 使用 PowerMockito 和 Mockito 模拟 FastDateFormat。
全部失败。我认为 setFinalStatic 方法是最接近的,但是我目前收到错误 ExceptionInInitializerError(正如用户 here and in Oracle Doc here 所讨论的那样)
事实证明,我的问题的答案是常量文件正在执行一些我必须模拟的初始化方法(在本例中:来自数据库的对象上的 safeGetTypeId(x))。
当我意识到 updateObjectId 硬编码测试正在运行并且 updateTimestamp 使用常量 class GTR_DATE_FORMAT.
时,我应该更快地注意到这一点构造函数是空的,我不希望执行任何其他内容。
这是一个极端复杂的问题,所以我可能会删除这个问题,但是如果它对以后的人有帮助,我会留下它。