Невозможно издеваться над конечным классом Kotlin с помощью Mockito 2
Я не могу издеваться над конечным классом Котлина, используя Mockito 2. Кроме того, я использую Robolectric.
Это мой тестовый код:
@RunWith(RobolectricTestRunner.class)
@Config(constants = BuildConfig.class, sdk = 21)
public class Test {
// more mocks
@Mock
MyKotlinLoader kotlinLoader;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
}
тест терпит неудачу, когда мы пытаемся инициализировать насмешки в setUp()
метод.
кроме того, я использую следующие зависимости gradle в своем коде:
testCompile 'org.robolectric:robolectric:3.3.2'
testCompile 'org.robolectric:shadows-multidex:3.3.2'
testCompile 'org.robolectric:shadows-support-v4:3.3.2'
testCompile("org.powermock:powermock-api-mockito2:1.7.0") {
exclude module: 'hamcrest-core'
exclude module: 'objenesis'
}
testCompile 'junit:junit:4.12'
testCompile 'org.mockito:mockito-inline:2.8.9'
все другие модульные тесты проходят с помощью этой конфигурации, но как только я пытаюсь издеваться над классом Kotlin, он бросает следующее ошибка:
Mockito cannot mock/spy because :
- final class
обратите внимание, что я использую Mockito версии 2, и я использую inline
зависимость, которая автоматически дает возможность издеваться над конечными классами.
3 ответов
вы можете использовать Powermock для этого, например:
import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.mockito.PowerMockito.spy;
import static org.powermock.api.mockito.PowerMockito.when;
@RunWith(RobolectricTestRunner.class)
@Config(constants = BuildConfig.class, sdk = 21)
@PowerMockIgnore({ "org.mockito.*", "org.robolectric.*", "android.*" })
@PrepareForTest({FinalClass1.class, FinalClass2.class})
public class Test {
@Rule
public PowerMockRule rule = new PowerMockRule();
... // your code here
}
PowerMock реализует свой собственный MockMaker
что приводит к несовместимости с Mockito mock-maker-inline, даже если PowerMock просто добавляется как зависимость и не используется. Если два org.mockito.plugins.MockMaker
существуют в пути, тогда можно использовать только один, который не определен.
PowerMock может, однако, делегировать вызовы другому MockMaker, а затем тесты запускаются без PowerMock. Начиная с PowerMock 1.7.0 это можно настроить с помощью конфигурации PowerMock.
В MockMaker можно настроить, создав файл org/powermock/extensions/configuration.properties
и настройка:
mockito.mock-maker-class=mock-maker-inline
пример использования Mockito mock-maker-inline с PowerMock:https://github.com/powermock/powermock-examples-maven/tree/master/mockito2
давайте программировать на интерфейсы, а не реализации. Вы можете извлечь интерфейс, использовать его в коде, и издеваться над ним. Например, не будет работать следующее:
import com.nhaarman.mockito_kotlin.mock
class MyFinalClass {...}
(snip)
private val MyFinalClass = mock()
Итак, давайте извлекем интерфейс:
class MyFinalClass : MyInterface {...}
(snip)
private val MyInterface = mock()