Почему экземпляр $ 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 требует явных аннотаций к числу допустимых членов.