我想测试一个调用对象的类(java中的静态方法调用),但我不能模拟这个对象以避免执行真正的方法。
object Foo {
fun bar() {
//Calls third party sdk here
}
}
@RunWith(PowerMockRunner::class)
@PrepareForTest(IntentGenerator::class)
class EditProfilePresenterTest {
@Test
fun shouldCallIntentGenerator() {
val intent = mock(Intent::class.java)
PowerMockito.mockStatic(IntentGenerator::class.java)
PowerMockito.`when`(IntentGenerator.newIntent(any())).thenReturn(intent) //newIntent method param is context
presenter.onGoToProfile()
verify(view).startActivity(eq(intent))
}
}
any()方法来自mockito_kotlin。然后,如果我将一个模拟上下文传递给newIntent方法,则似乎调用了real方法。
首先,对象IntentGenerator
看起来像是一种代码气味,为什么要使它成为对象
?如果它不是您的代码,您可以轻松地创建一个包装类
class IntentGeneratorWrapper {
fun newIntent(context: Context) = IntentGenerator.newIntent(context)
}
并在代码中使用它,而不需要静态依赖关系。
话虽如此,我有两个解决方案。假设您有一个对象
object IntentGenerator {
fun newIntent(context: Context) = Intent()
}
testCompile "io.mockk:mockk:1.7.10"
testCompile "com.nhaarman:mockito-kotlin:1.5.0"
然后在测试中使用objectmockk
fun与object
作为参数,这将返回一个作用域,在该作用域上调用use
。在use
正文中,您可以模拟对象
:
@Test
fun testWithMockk() {
val intent: Intent = mock()
whenever(intent.action).thenReturn("meow")
objectMockk(IntentGenerator).use {
every { IntentGenerator.newIntent(any()) } returns intent
Assert.assertEquals("meow", IntentGenerator.newIntent(mock()).action)
}
}
解决方案2-模仿+反射
在您的测试资源文件夹中创建一个mockito-extensions
文件夹(例如,如果您的模块是“app”->app/src/test/resources/mockito-extensions
),并在其中创建一个名为org.mockito.plugins.mockmaker
的文件。在文件中,只需编写这一行mock-maker-inline
。现在可以模拟final类和方法(IntentGenerator
类和NewIntent
方法都是final的)。
那你需要
IntentGenerator
的实例。请注意,IntentGenerator
只是一个普通的java类,我邀请您在Android StudioKotlin Bytecode
窗口检查它
instance
字段中删除最终修饰符。在Kotlin中声明Object
时,发生的情况是使用私有构造函数和静态Instance
方法创建类(在本例中为IntentGenerator
)。即单例。IntentGenerator.Instance
值替换为您自己的模拟实例。完整的方法如下所示:
@Test
fun testWithReflection() {
val intent: Intent = mock()
whenever(intent.action).thenReturn("meow")
// instantiate IntentGenerator
val constructor = IntentGenerator::class.java.declaredConstructors[0]
constructor.isAccessible = true
val intentGeneratorInstance = constructor.newInstance() as IntentGenerator
// mock the the method
val mockedInstance = spy(intentGeneratorInstance)
doAnswer { intent }.`when`(mockedInstance).newIntent(any())
// remove the final modifier from INSTANCE field
val instanceField = IntentGenerator::class.java.getDeclaredField("INSTANCE")
val modifiersField = Field::class.java.getDeclaredField("modifiers")
modifiersField.isAccessible = true
modifiersField.setInt(instanceField, instanceField.modifiers and Modifier.FINAL.inv())
// set your own mocked IntentGenerator instance to the static INSTANCE field
instanceField.isAccessible = true
instanceField.set(null, mockedInstance)
// and BAM, now IntentGenerator.newIntent() is mocked
Assert.assertEquals("meow", IntentGenerator.newIntent(mock()).action)
}
问题是,在模拟对象之后,模拟的实例将停留在那里,其他测试可能会受到影响。A制作了一个示例,说明如何将嘲讽限制在一个范围内
为什么PowerMock不能工作
PowerMockito.mockStatic(IntentGenerator::class.java)
PowerMockito.doAnswer { intent }.`when`(IntentGenerator).newIntent(any())
notaMockException:传递给when()不是模拟的参数!
如果对象被模拟,则调用的newInstance
方法将不是来自实际类的方法,因此即使在签名中null
不可为空,也可以作为参数传递
给定一个Kotlin单例对象和一个调用它的方法的乐趣
我有一个示例方法(我需要编写测试用例)如下所示, 我想模拟getConfig方法并返回一个特定的字符串值。getConfig是Kotlin对象中方法,如下所示, 下面是我尝试的测试 我没有得到任何错误,但是getConfig方法没有被嘲笑。执行实际的实现。我也试过使用Powermockito。请帮帮我
我试图用Kotlin中的jMockit模拟一个静态方法: 但我得到以下错误:
我想模拟注释来检查根据给定注释返回结果的类的良好行为。 Erg.mockito.exceptions.misusing.WurnTypeOfReturnValue:annotationType()不能返回KClassImpl annotationType()应该返回Class 如果你不确定为什么你会超过错误,请继续阅读。由于语法的性质,上面的问题可能会发生,因为: 此异常可能发生在错误编写的多线程
如何模拟返回已强制转换的模拟对象的方法。 试验方法。
问题内容: 我在Python2中有以下代码段: 我想为其编写一些单元测试。我想知道如何使用它来修补游标和连接变量,以便它们返回伪造的数据集?我已经为单元测试尝试了以下代码段,但无济于事: 但是我似乎收到以下错误: 问题答案: 由于游标是的返回值,因此您只需模拟连接,然后正确配置它。例如,