Почему экземпляр $ MockitoMock $ не идентифицируется как макет?

Я использую Kotlin, Mockito и MockitoJRunner для запуска следующего упрощенного теста:

open class SomeClassToBeMocked @Inject constructor() { fun map(foo: Foo): Bar {...} } @Mock private lateinit var someMock: SomeClassToBeMocked @InjectMocks private lateinit var subject: Subject @Test fun shouldAssertSomething() { val foo = Foo() // from Foo.kt val bar = Bar() // from Bar.java from *another module* whenever(someMock.map(foo)).thenReturn(bar) // breakpoint[1] subject.myMethod(foo) verify(someMock).map(foo) } 

Этот шаблон работает в других частях кода, но не в этом конкретном тесте, где появляется следующее сообщение об ошибке:

 org.mockito.exceptions.misusing.MissingMethodInvocationException: when() requires an argument which has to be 'a method call on a mock'. For example: when(mock.getArticles()).thenReturn(articles); Also, this error might show up because: 1. you stub either of: final/private/equals()/hashCode() methods. Those methods *cannot* be stubbed/verified. Mocking methods declared on non-public parent classes is not supported. 2. inside when() you don't call method on mock but on some other object. 

Когда я отлаживаю код в точке breakpoint[1] , я вижу, что someMock является экземпляром класса SomeClassToBeMocked$MockitoMock$ . Кроме того, если я пытаюсь вызвать someMock.map(foo) непосредственно перед breakpoint[1] , он действительно запускает оригинальный метод, вместо того, чтобы возвращать null как и все mocks.

Любые идеи о том, что может происходить здесь?

UPDATE-1 : я проверил все возможности для опции 1 в сообщении об ошибке. Я также попробовал mock(SomeClassToBeMocked::class.java) и получил то же сообщение об ошибке. Это последовательно происходит с некоторыми простейшими классами, с одним открытым методом, который преобразует только объект A в объект B.

ОБНОВЛЕНИЕ-2 : Если это имеет значение, я просто заметил, что в тех случаях, когда это происходит, Bar() живет в другом модуле, чем тесты. Я обновил код, чтобы отразить это.

UPDATE-3 : если я создаю интерфейс SomeClassToBeMocked и переименую оригинальный класс в SomeClassToBeMockedImpl , все работает как шарм. Тем не менее, я все равно хотел бы выяснить, почему это происходит и как избежать создания для этого интерфейса.

Чтобы высмеять возвращаемое значение функции с помощью Mockito, вам нужно пометить ее ключевым словом open :

 open class SomeClassToBeMocked @Inject constructor() { open fun map(foo: Foo): Bar {...} } 

Проблема в том, что Мокито не может высмеивать окончательные (которые не могут быть переопределены) функциями. В отличие от Java, Kotlin требует явных аннотаций к числу допустимых членов.

Intereting Posts
Ожидается, что в Котлине ожидается активатор или сеттер Android WebView прыгает вверху каждого обновления страницы (?) Невозможно использовать SQS от Lambda Класс не найден, пустой набор тестов в androidTest с использованием Android Studio 3.0.1, Room, Kotlin Функция инициализации массива Котлина Передача приложения в AndroidViewModel Как сохранить имена параметров для отладки? расширение функции для класса в другом классе раньше в Котлине Определите глобальную функцию в Kotlin, которую я буду использовать в html-файле для использования в качестве обратного вызова onclick Vert.x Kotlin Тип Несоответствие требуется Обработчик <AsyncResult <Unit >> found (Обработчик <AsyncResult <Unit >>) -> Unit «kapt.generateStubs» не используется плагином «kotlin-kapt» Kotlin: gettng rid Unchecked casts для Comparable Как написать преобразование многократного использования для значения String to Enum в группе классов Enum? (Котлин) Отображение Firebase в Kotlin-Object не работает