2015-08-11 7 views
-2

Я хотел написать тест для своих изменений, но получил проблемы - изменения были сделаны внутри статического метода. кода выглядит следующим образомЕсть ли способы издеваться над статическими методами с помощью mockito?

class GlobalData { 
static boolean doSomething(...){...} 
static xxx A() {...} 
static yyy B() {...} 
static void C() { 
xxx a = A(); 
yyy b = B(); 

if (doSomething(a, b)) 
{ 
    a.xyz(b,42); 
    ... my coode i want to test.... 
} 
} 

То, что я хочу, чтобы макет методы А и В и DoSomething и всех эти статические методы, которые используются в методе C, но я не могу найти способ сделать это на момент. У вас теперь есть?

ответ

3

Рассмотрите возможность использования powerMock. Он имеет расширение над Мокито, называемое «powerMockito». Это дает вам возможность также издеваться над статическими методами. https://github.com/jayway/powermock/wiki/MockitoUsage

0

Поскольку вы не можете переопределить статические методы, нет, вы не можете имитировать их в Mockito.

+0

не с одной только Mockito, но с Powermockito вы можете: http://www.codeproject.com/Articles/806508/Using-PowerMockito-to-Mock-Final-and-Static-Method –

+0

ОП Ждут» Спросите о Powermockito. Итак ... Я поддерживаю свой ответ. –

+0

Вы можете использовать PowerMockito. –

0

Вы должны/могли бы использовать шаблон Singleton.

В основном все статические методы вызывают внутренний частный объект, который выполняет фактическую логику (называемый экземпляром).

Если вы сделаете это, вы можете предоставить защищенный статический метод setInstance. Во время теста вы создаете посмеянный экземпляр и установите его в статический класс.

Это выполнимо, но это не самое элегантное решение, но статические вызовы не настолько элегантны в первую очередь. Я отвечаю, как не было никакой возможности, чтобы реорганизовать из всего кодовых (например, с помощью Dependency Injection, например)

Например:

class GlobalData { 
    //private object that does all the actual logic 
    private static GlobalData instance = new GlobalData(); 

    //constructor is private so no one can call it 
    private GlobalData() { 

    } 

    //delegate the static call to the internal instance 
    static boolean doSomething(...){ return instance._doSomething(); } 

    //use underscore to keep similar name but avoid ambiguous call 
    private boolean _doSomething(...){ ... } 

    //same here 
    static xxx A() { return instance._A(); } 
    private xxx _A() {...} 

    //this is not public, so must be called from the same package 
    //since the constructor is private, no one will be able to create a GlobalData 
    //except for mockito 
    static void setInstance(GlobalData instance) { 
     GlobalData.instance = instance; 
    } 
} 

, а затем в тесте (который должен быть в том же пакете):

GlobalData instanceMocked = mock(GlobalData.class); 
//we mock the methods with underscore, as they are the instance methods, and 
//not the class methods 
when(instanceMocked._A()).thenReturn(whatever); 
when(instanceMocked._doSomething()).thenReturn(whatever); 
GlobalData.setInstance(instanceMocked); 

Для этого требуется лишь незначительное рефакторинг в классе вы смотрите, не касаясь остальной части проекта, в то время как достижения того, что вы хотите.

+0

Я использовал этот подход в прошлом, и он действительно работает. Есть проблемы с этим, но это приводит к упрощению тестирования модулей, а затем к статическим методам. –

+0

Точно. Не злоупотребляйте этим и не считайте его отличной практикой. –

+0

Еще один момент для этого подхода. Хотя вы можете использовать PowerMockito для издевательства статических методов, если испортили наши отчеты JaCoCo. Манипулирование байтового кода, которое делает PowerMockito, нарушило манипуляции с байт-кодом JaCoCo. Я уверен, что то же самое может быть верно для любого другого инструмента покрытия кода. –

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