У меня есть последний класс, что-то вроде этого:
public final class RainOnTrees{
public void startRain(){
// some code here
}
}
Я использую этот класс в каком-то другом классе, как это:
public class Seasons{
RainOnTrees rain = new RainOnTrees();
public void findSeasonAndRain(){
rain.startRain();
}
}
и в моем тестовом классе JUnit Seasons.java
я хочу издеваться над RainOnTrees
классом. Как я могу сделать это с Mockito?
Ответы:
Пересмешивать финальные / статические классы / методы возможно только в Mockito v2.
добавьте это в свой файл Gradle:
Это невозможно с Mockito v1, из FAQ по Mockito :
источник
Mockito 2 теперь поддерживает финал классы и методы!
Но пока это «инкубационная» особенность. Требуется несколько шагов для его активации, которые описаны в в разделе Что нового в Mockito 2 :
источник
org.mockito.plugins.MockMaker
файл в правильную папку.Вы не можете издеваться над последним классом с Mockito, как вы не можете сделать это самостоятельно.
Что я делаю, так это создаю не финальный класс, чтобы обернуть последний класс и использовать его в качестве делегата. Примером этого является
TwitterFactory
класс, и это мой смешной класс:Недостаток в том, что здесь много шаблонного кода; Преимущество заключается в том, что вы можете добавить некоторые методы, которые могут относиться к вашему бизнесу приложений (например, getInstance, который принимает пользователя вместо accessToken, в приведенном выше случае).
В вашем случае я бы создал не финальный
RainOnTrees
класс, который делегировал бы финальный класс. Или, если вы можете сделать это не финальным, было бы лучше.источник
@Delegate
для обработки большого количества шаблонов.добавьте это в свой файл Gradle:
это конфигурация для работы mockito с последними классами
источник
org.mockito.exceptions.base.MockitoInitializationException: Could not initialize inline Byte Buddy mock maker. (This mock maker is not supported on Android.)
Используйте Powermock. Эта ссылка показывает, как это сделать: https://github.com/jayway/powermock/wiki/MockFinal
источник
Powermock
для насмешки над финальными классами и статическими методами, чтобы увеличить мой охват, который был официально проверенSonarqube
. После SonarQube охват составил 0%, по какой-либо причине не распознает классы, которые используют Powermock где-либо внутри него. Я потратил некоторое время на то, чтобы осознать это в своей сети. Так что это только одна из причин быть осторожным с Powermock и, вероятно, не использовать его.Просто чтобы продолжить. Пожалуйста, добавьте эту строку в ваш файл Gradle:
Я пробовал разные версии мокито-ядра и мокито-все. Ни один из них не работает.
источник
Я полагаю, вы сделали это
final
потому, что хотите предотвратить расширение других классовRainOnTrees
. Как предлагает Effective Java (пункт 15), есть другой способ держать класс закрытым для расширения, не делая егоfinal
:Удалить
final
ключевое слово;Сделай свой конструктор
private
. Ни один класс не сможет расширить его, потому что он не сможет вызватьsuper
конструктор;Создайте статический метод фабрики для создания экземпляра вашего класса.
Используя эту стратегию, вы сможете использовать Mockito и держать свой класс закрытым для расширения с помощью небольшого стандартного кода.
источник
У меня такая же проблема. Поскольку класс, который я пытался смоделировать, был простым классом, я просто создал его экземпляр и возвратил его.
источник
Попробуйте это:
Это сработало для меня. SomeMockableType.class является родительским классом того, что вы хотите шутить или шпионить, а someInstanceThatIsNotMockableOrSpyable является фактическим классом, который вы хотите шутить или шпионить.
Для более подробной информации смотрите здесь
источник
Другой обходной путь, который может применяться в некоторых случаях, заключается в создании интерфейса, реализуемого этим последним классом, изменении кода для использования интерфейса вместо конкретного класса, а затем макете интерфейса. Это позволяет отделить контракт (интерфейс) от реализации (конечный класс). Конечно, если то, что вы хотите, действительно связать с последним классом, это не будет применяться.
источник
На самом деле есть один способ, которым я пользуюсь для шпионажа. Это будет работать для вас, только если выполнены два предварительных условия:
Пожалуйста, вспомните пункт 16 из Эффективной Java . Вы можете создать оболочку (не финальную) и переслать все вызовы экземпляру финального класса:
Теперь вы можете не только высмеивать ваш последний класс, но и следить за ним:
источник
В Mockito 3 и более у меня такая же проблема и исправлена как по этой ссылке
Пробные финальные классы и методы с Mockito следующим образом
источник
Экономия времени для людей, которые сталкиваются с той же проблемой (Mockito + Final Class) на Android + Kotlin. Как и в Kotlin классы являются окончательными по умолчанию. Я нашел решение в одном из примеров Google Android с компонентом Architecture. Решение выбрано отсюда: https://github.com/googlesamples/android-architecture-components/blob/master/GithubBrowserSample
Создайте следующие аннотации:
Измените свой файл Gradle. Возьмите пример отсюда: https://github.com/googlesamples/android-architecture-components/blob/master/GithubBrowserSample/app/build.gradle
Теперь вы можете аннотировать любой класс, чтобы открыть его для тестирования:
источник
Это можно сделать, если вы используете Mockito2, с новой функцией инкубации, которая поддерживает насмешку над финальными классами и методами.
Ключевые моменты, на которые следует обратить внимание:
1. Создайте простой файл с именем «org.mockito.plugins.MockMaker» и поместите его в папку с именем «mockito-extensions». Эта папка должна быть доступна на пути к классам.
2. Содержимое файла, созданного выше, должно быть одной строкой, как указано ниже:
mock-maker-inline
Вышеупомянутые два шага необходимы, чтобы активировать механизм расширения мокито и использовать эту дополнительную функцию.
Примеры классов следующие:
FinalClass.java
}
Foo.java
}
FooTest.java
}
Надеюсь, поможет.
Полная статья, представленная здесь, издевается над немодным .
источник
Да, та же проблема здесь, мы не можем издеваться над последним классом с Mockito. Чтобы быть точным, Mockito не может издеваться над шпионом:
Но использование класса-обертки мне кажется большой ценой, поэтому вместо этого получите PowerMockito.
источник
Я думаю, вам нужно больше думать в принципе. Вместо этого в последнем классе вы используете его интерфейс и макет интерфейса.
Для этого:
Добавить
и издеваться над интерфейсом:
источник
Пожалуйста, посмотрите на JMockit . Он имеет обширную документацию с множеством примеров. Здесь у вас есть пример решения вашей проблемы (чтобы упростить, я добавил конструктор,
Seasons
чтобы внедрить смоделированныйRainOnTrees
экземпляр):источник
Решения, предоставленные RC и Luigi R. Viggiano вместе, возможно, лучшая идея.
Хотя Mockito не может , по замыслу, издеваться над последними классами, возможен подход делегирования . Это имеет свои преимущества:
В вашем тестовом случае вы сознательно перенаправляете вызовы в тестируемую систему. Следовательно, по дизайну, ваше украшение ничего не делает.
Следовательно, тестирование также может продемонстрировать, что пользователь может только украшать API, а не расширять его.
На более субъективной ноте: я предпочитаю сводить рамки к минимуму, поэтому для меня обычно достаточно JUnit и Mockito. На самом деле, ограничение таким образом иногда заставляет меня и рефакторинг навсегда.
источник
Если вы пытаетесь запустить юнит-тест в папке test , лучшее решение - это хорошо. Просто следуйте этому добавлению расширения.
Но если вы хотите запустить его с классом, связанным с Android, таким как контекст или действие, которое находится в папке androidtest , ответ для вас.
источник
Добавьте эти зависимости для успешного запуска mockito:
testImplementation 'org.mockito: mockito-core: 2.24.5'
testImplementation "org.mockito: mockito-inline: 2.24.5"
источник
Как уже говорили другие, это не будет работать из коробки с Mockito. Я бы предложил использовать рефлексию для установки определенных полей объекта, который используется тестируемым кодом. Если вы обнаружите, что делаете это много, вы можете поместить эту функцию в библиотеку.
Кроме того, если вы один из тех, кто отмечает финальные классы, прекратите это делать. Я столкнулся с этим вопросом, потому что я работаю с API, где все было помечено как окончательное, чтобы предотвратить мою законную необходимость расширения (насмешки), и я хотел бы, чтобы разработчик не предполагал, что мне никогда не понадобится расширять класс.
источник
final
должно быть по умолчанию.Для нас это было потому, что мы исключили mockito-inline из koin-test. Один модуль gradle действительно нуждался в этом, и по причине сбой только при сборках релиза (отладочные сборки в IDE работали) :-P
источник
Для финального класса добавьте ниже к макету и назовите статический или нестатический.
1 - добавьте это на уровне класса @SuppressStatucInitializationFor (value = {имя класса с пакетом})
2 - PowerMockito.mockStatic (classname.class) будет имитировать класс
3 - затем используйте оператор when для возврата фиктивного объекта при вызове метода этого класса.
наслаждаться
источник
Не пробовал финал, но для частного использования с помощью отражения удалить модификатор сработало! проверил дальше, это не работает для финала.
источник