Как издеваться над статическим методом без powermock

Есть ли способ, которым мы можем высмеивать статический метод util во время тестирования в JUnit?

Я знаю, что Powermock может высмеивать статические вызовы, но я не хочу использовать Powermock.

Есть ли альтернативы?

Ответ 1

(Я предполагаю, что вы можете использовать Mockito, хотя) Ничего особенного мне не приходит в голову, но я склонен использовать следующую стратегию, когда дело доходит до таких ситуаций:

1) В тестируемом классе замените прямой статический вызов на вызов метода уровня пакета, который включает сам статический вызов:

public class ToBeTested{

    public void myMethodToTest(){
         ...
         String s = makeStaticWrappedCall();
         ...
    }

    String makeStaticWrappedCall(){
        return Util.staticMethodCall();
    }
}

2) Шпионить тестируемый класс во время тестирования и смоделировать метод уровня упакованного пакета:

public class ToBeTestedTest{

    @Spy
    ToBeTested tbTestedSpy = new ToBeTested();

    @Before
    public void init(){
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void myMethodToTestTest() throws Exception{
       // Arrange
       doReturn("Expected String").when(tbTestedSpy).makeStaticWrappedCall();

       // Act
       tbTestedSpy.myMethodToTest();
    }
}

Вот статья, которую я написал о шпионаже, в которой есть похожий случай, если вам нужно больше информации: sourceartists.com/mockito-spying

Ответ 2

Когда у вас есть статический код, который дает вам проблемы в ваших модульных тестах; так что вы чувствуете, что вам нужно "издеваться", у вас есть именно такие варианты:

  • Вы переходите к PowerMock (ito). Прекрасно работает.
  • Вы обращаетесь к JMockit. Хорошо работает тоже.
  • Если вы тестируете код, который вы сами написали, вам может потребоваться отступить и спросить себя: "Почему я написал код, который теперь мне трудно найти unit test?"

Другими словами: если вы хотите использовать фальшивую фреймворк, вы должны использовать один из перечисленных выше. С одной стороны, это абсолютно справедливо. static - это одна часть языка Java; так почему бы не использовать фреймворк, который позволяет вам справиться с этим?

Но, конечно же, у вас все еще есть статический вызов в вашем производственном коде. Приводя к жесткой связи и предотвращая полиморфизм.

Итак: если вы можете избавиться от статического вызова (даже при использовании обходного пути, предложенного в другом ответе), тем лучше. Если нет: Мокито не может помочь; вам понадобится магия манипуляции с байтовым кодом или. Агенты JVM.

Ответ 3

Мне очень повезло, когда я сделал что-то похожее на то, что Мачей предложил в своем ответе выше. В Java8 мне нравится оборачивать эти статические методы функциональными интерфейсами, чтобы сделать их более простыми для внедрения или имитации. Например:

public class MyClass {
    private MyStaticWrapper staticWrapper;

    public MyClass(final MyStaticWrapper staticWrapper) {
        this.staticWrapper = staticWrapper;
    }

    public void main() {
        ...
        staticWrapper.doSomething();
        ...    
    }
}    

public interface MyStaticWrapper {
    default void doSomething() {
      Util.annoyingUntestableStaticFunction();
    }
}