簡體   English   中英

如何模擬在另一個類中使用另一個靜態最終變量的變量

[英]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 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解決方案 ,該解決方案可以成功地與我正在進行的其他測試一起使用。

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方法
  • 使用PowerMockito和Mockito產生模擬常量。
  • 使用PowerMockito和Mockito模擬GTR_DATE_FORMAT實例。
  • 使用PowerMockito和Mockito模擬FastDateFormat。

所有這些都失敗了。 我認為setFinalStatic方法是最接近的方法,但是我目前遇到了ExceptionInInitializerError錯誤(也從此處的用戶以及此處的Oracle Doc中進行了討論

事實證明,對我的問題的答案是,Constants文件正在執行一些我必須模擬的初始化方法(在這種情況下:對來自數據庫的對象的safeGetTypeId(x))。

當意識到使用常量類GTR_DATE_FORMAT的updateObjectId硬編碼測試正在運行並且updateTimestamp正常運行時,我應該注意到這一點。

構造函數是空的,我沒想到會執行其他任何操作。

這是一個極端而復雜的問題,因此我可以刪除此問題,但是如果將來可以幫助某個人,我將不予理會。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM