我无法使用Mockito 2模拟Kotlin决赛课。我还在使用Robolectric。
这是我的测试代码:
for
当我们尝试在@RunWith(RobolectricTestRunner.class)
@Config(constants = BuildConfig.class, sdk = 21)
public class Test {
// more mocks
@Mock
MyKotlinLoader kotlinLoader;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
}
方法中初始化模拟时,测试失败。
另外,我在代码中使用了以下gradle依赖项:
setUp()
所有其他单元测试都使用此配置,但是一旦我尝试模拟Kotlin类,它就会抛出以下错误:
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'
请注意我使用的是Mockito版本2,我使用的是Mockito cannot mock/spy because :
- final class
依赖项,它可以自动启用模拟最终类的功能。
答案 0 :(得分:13)
PowerMock实现了自己的MockMaker
,这导致与Mockito mock-maker-inline不兼容,即使PowerMock刚刚作为依赖项添加而未被使用。如果路径中存在两个org.mockito.plugins.MockMaker
,则可以使用任何一个org/powermock/extensions/configuration.properties
,其中一个未确定。
然而,PowerMock可以将调用委托给另一个MockMaker,然后在没有PowerMock的情况下运行测试。从PowerMock 1.7.0开始,可以使用PowerMock配置对其进行配置。
可以通过创建文件mockito.mock-maker-class=mock-maker-inline
并设置:
Z
使用Mockito mock-maker-inline和PowerMock的示例:https://github.com/powermock/powermock-examples-maven/tree/master/mockito2
答案 1 :(得分:2)
自Mockito 2.1.0起,就有可能模拟最终类型,枚举和最终方法。在原始问题的注释中已经提到了它。
为此,您需要创建一个文件夹(如果不存在)test/resources/mockito-extensions
,然后在其中添加名称为org.mockito.plugins.MockMaker
的文件并添加以下行:
mock-maker-inline
答案 2 :(得分:1)
您可以使用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
}
答案 3 :(得分:0)
让我们编程接口,而不是实现。您可以提取接口,在代码中使用它并模拟它。例如,以下内容不起作用:
import com.nhaarman.mockito_kotlin.mock
class MyFinalClass {...}
(snip)
private val MyFinalClass = mock()
所以让我们提取一个界面:
class MyFinalClass : MyInterface {...}
(snip)
private val MyInterface = mock()
答案 4 :(得分:0)
因为在kotlin中,所有类默认都是final。
您还应该考虑将native query
添加到类声明中。
示例:jpql
答案 5 :(得分:0)
Kotlin使装饰器模式完全简单且简洁:
open class OpenClass() : SomeInterface by FinalClass()
实际上,这将对SomeInterface
包装类中的FinalClass()
实例进行包装调用来覆盖每个open
成员。然后,您可以将此包装器注入测试中。
我不得不在目标类位于库中的项目上求助,并且all-open
编译器插件似乎无法触及。
答案 6 :(得分:0)
尝试将此以下依赖项添加到您的build.gradle中。
{{1}}
替换为您的模仿版本,而不是2.8.47。这将帮助您避免使用powermock解决问题。
请查看下面的链接,以了解此事情的工作原理。
答案 7 :(得分:0)
mock-maker-inline
的工作方式与其他答案中所指出的一样。但这真的很慢。您可以使用all-open
插件来避免此问题。
为此,您需要:
annotation class Mockable
build.gradle
文件中的全开:dependencies {
classpath "org.jetbrains.kotlin:kotlin-allopen:$kotlin_version"
}
apply plugin: 'kotlin-allopen'
allOpen {
annotation('com.example.Mockable')
}
@Mockable
class Foo {
fun calculateTheFoo(): Int {
sleep(1_000) // Difficult things here
return 1
}
}
如果您想了解更多信息,可以阅读我的博客文章,我在其中详细介绍了这些内容:Mocking Kotlin classes with Mockito — the fast way