簡體   English   中英

如何使用PowerMockito在具有私有構造函數的類中設置原始私有靜態final字段?

[英]How do I set a primitive private static final field in a class with private constructor using PowerMockito?

我正在嘗試使用private構造函數在類中設置private static final字段以進行JUnit測試。 當我將代碼簡化為基礎時,我得到以下內容:

public class Foo {
    private static final boolean FLAG = false;
    private Foo() { /* don't call me */  }
    public static boolean get() { return FLAG; }
}

我的測試看起來像這樣:

@RunWith(PowerMockRunner.class)
@PrepareEverythingForTest  // Whitebox fails without this line
public class FooTest {
    @Test
    public void testGet() {
        Whitebox.setInternalState(Foo.class, "FLAG", true);
        assertTrue(Foo.get());
    }
}

這是我的POM文件的摘錄:

<junit.version>4.11</junit.version>
<powermock.version>1.5.4</powermock.version>
<mockito.version>1.9.5</mockito.version>

當我在return FLAG;時設置斷點return FLAG; ,我可以清楚地看到IntelliJ的調試器中FLAG設置為true 然而,測試因AssertionError而失敗。

任何想法如何使這項工作?

更新:使用反射似乎不起作用,或者:

@Test
public void testGet_usingReflection() throws Exception {
    setField(Whitebox.invokeConstructor(Foo.class), "FLAG", true);
    assertTrue(Foo.get());
}

public static void setField(Object targetObject, String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException {
    Class clazz =  targetObject.getClass();
    Field field = clazz.getDeclaredField(fieldName);
    field.setAccessible(true);
    Field modifiers = Field.class.getDeclaredField("modifiers");
    modifiers.setAccessible(true);
    modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL);
    field.set(targetObject, value);
}

setField()方法是我通過內部庫提供的方法。 不幸的是,它產生了相同的結果: AssertionError

更新2:完全擺脫PowerMock也沒有多大幫助,顯然:

@Test
public void testGet_usingReflectionWithoutPowerMock() throws Exception {
    setField(Foo.class.getDeclaredField("FLAG"), true);
    assertTrue(Foo.get());
}

public static void setField(Field field, Object value) throws NoSuchFieldException, IllegalAccessException {
    field.setAccessible(true);
    Field modifiers = Field.class.getDeclaredField("modifiers");
    modifiers.setAccessible(true);
    modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL);
    field.set(null, value);
}

為此,我甚至從班級中刪除了PowerMock注釋......

我現在也將這個問題發布到PowerMock郵件列表中

我有類似的東西要測試,但唯一的區別是我的靜態最終變量是一個Object而不是原始類型。 實際上,將boolean Boolean更改為Boolean會使其工作。

public class Foo {
    private static final Boolean FLAG = false;
    private Foo() { /* don't call me */  }
    public static boolean get() { return FLAG; }
}

另外我建議使用@PrepareForTest(SomeClass.class) ,其中SomeClass具有靜態最終字段而不是@PrepareEverythingForTest因為如果它是大項目,可能需要一些時間准備一切。

WhiteBox.setInternalState不適用於帶有final字段的類。

您可以使用Reflection來解決此問題:

static void setFinalStatic(Field field, Object newValue) throws Exception {  
  field.setAccessible(true);  

  Field modifiersField = Field.class.getDeclaredField("modifiers");  
  modifiersField.setAccessible(true);  
  modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);  

  field.set(null, newValue);  
}  

來源: https//code.google.com/p/powermock/issues/detail?id = 324

暫無
暫無

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

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