Почему Mockito не издевается над статическими методами?

Я прочитал несколько потоков здесь о статических методах, и я думаю, что понимаю проблемы, которые могут вызвать неправильное использование/чрезмерное использование статических методов. Но я действительно не понял, почему сложно издеваться над статическими методами.

Я знаю, что другие насмешливые фреймворки, такие как PowerMock, могут это сделать, но почему Mockito не может?

Я читаю эту статью, но автор, похоже, религиозно против слова static, может быть, это мое плохое понимание.

Легкое объяснение/ссылка будет замечательной.

Ответ 1

Я думаю, что причиной может быть то, что библиотеки макетных объектов обычно создают mocks путем динамического создания классов во время выполнения (используя cglib). Это означает, что они либо реализуют интерфейс во время выполнения (что делает EasyMock, если я не ошибаюсь), либо они наследуют от класса, чтобы высмеивать (что то, что делает Mockito, если я не ошибаюсь). Оба подхода не работают для статических членов, поскольку вы не можете переопределить их с помощью наследования.

Единственный способ издеваться над статикой - это модифицировать байтовый код класса во время выполнения, что, я полагаю, немного больше связано с наследованием.

Что я думаю об этом, за что это стоит...

Ответ 2

Если вам нужно издеваться над статическим методом, это сильный индикатор плохой конструкции. Обычно вы издеваетесь над зависимостью вашего класса от теста. Если ваш класс под тестом относится к статическому методу - например, к java.util.Math # sin - это означает, что для класса-теста требуется именно эта реализация (например, с точностью до скорости). Если вы хотите абстрагироваться от конкретной реализации синуса, вам, вероятно, нужен интерфейс (вы видите, где это происходит)?

Ответ 3

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

  • Статические методы для доступа к общей функциональности? → Использовать экземпляр singleton и добавить, что
  • Сторонний код? → Оберните его в свой собственный интерфейс/делегат (и при необходимости сделайте его одиночным) тоже.

Единственный раз, когда это кажется мне лишним, - это libs, как Guava, но вам не нужно издеваться над этим видом, так или иначе, потому что это часть логики... (такие вещи, как Iterables.transform(..))
Таким образом, ваш собственный код остается чистым, вы можете изнашивать все ваши зависимости в чистом виде, и у вас есть слой антикоррозийной защиты от внешних зависимостей. Я видел PowerMock на практике, и все классы, в которых мы нуждались, были плохо разработаны. Также интеграция PowerMock порой вызывала серьезные проблемы (например, https://code.google.com/p/powermock/issues/detail?id=355)

PS: То же относится и к закрытым методам. Я не думаю, что тесты должны знать о деталях частных методов. Если класс настолько сложный, что он искушает издеваться над частными методами, это, вероятно, знак для разделения этого класса...

Ответ 4

Mockito возвращает объекты, но static означает "уровень класса, а не уровень объекта". Таким образом, mockito предоставит исключение для нулевого указателя для статического.

Ответ 5

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