2016-04-23 1 views
1

Я пытаюсь протестировать следующий класс, который вызывает один синглтон, который инициализирует приватную статическую конечную переменную, издеваясь над ней, следуя примеру this.Что я делаю неправильно, высмеивая эту приватную статическую конечную переменную, используя mockito и reflection?

Вот что я делаю

public class ClassToTest { 

private static final boolean CONF_FLAG = Configuration.getConfig() 
.get(Status.Initialization).getConfFlag(); // throws an NPE 

public methodToTest(TestObject a){ 
... 
} 
} 

где положение является Enum.

Класс испытаний:

public class TestClassToTest{ 

TestObject a; 
ClassToTest t; 
    @Before 
public void setUp() throws Exception { 
    setFinalStatic(ClassToTest.class.getDeclaredField("CONF_FLAG"), true);// this fails! 
    a = mock(TestObject.class); 
    t = new ClassToTest(); 
} 
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); 
} 

}

Я не забочусь о стоимости CONF_FLAG, но не могу показаться, чтобы дразнить его. Что я делаю не так?

ответ

1

Когда класс загружен, то эта линия называется

private static final boolean CONF_FLAG = Configuration.getConfig().get(Status.Initialization).getConfFlag(); 

Таким образом, чтобы решить эту проблему, я хотел бы предложить использовать PowerMock.

С помощью PowerMock вы можете легко пропустить unnecessary behavior с помощью @SuppressStaticInitilizationFor.

Кроме того, вы сможете легко установить внутреннее состояние:

Whitebox.setInternalState(ClassToTest.class, "CONF_FLAG", true) 

Конечно, он будет работать в том случае, если вы можете добавить новую библиотеку.

1

Ваш код в TestClassToTest выглядит нормально, но доступ к ClassToTest.class.getDeclaredField("CONF_FLAG") будет инициализировать статический окончательный ClassToTest#CONF_FLAG поле, которое Вы указываете результаты в NullPointerException.

Я предполагаю, что вы не можете изменить исходный код в ClassToTest. Как исправить, есть ли что-нибудь дополнительное, что вы можете сделать в setUp(), чтобы инициализировать singleton Configuration, например, используя его общедоступные методы API, чтобы вызов Configuration.getConfig().get(Status.Initialization).getConfFlag() преуспел?

Если это так, вы можете использовать этот подход для подготовки объекта Configuration для своих тестов, а не для отражения.

+0

+1. Чтобы добавить сюда, если вызов происходит как часть инициализации статического поля, у вас будет мало контроля за временем вызова, и у него фактически не будет возможности заменить его на тесты. Как правило, если вызов достаточно опасен, чтобы, возможно, выбросить исключение или заставить насмехаться в тестах, вы не хотите его в каком-либо статическом инициализаторе. –

+0

@Jeff Bowman, @ ck1 Да, я полностью понимаю, что не ставить его в статическом инициализаторе, но это часть устаревшего кода, с которым мне ударили, и я вроде как пытаюсь поработать вокруг него. Предполагая, что 'getConfig()' является статическим методом .. есть ли способ, который я могу издеваться/заглушить весь вызов в singleton? Если да, Id очень ценит некоторый код/​​псевдокод. – MuleNoob

Смежные вопросы