切换到Kotlin时,静态方法将移入一个伴随对象。但是,没有明显的方法可以对称为“静态方法”的其他方法进行单元测试。
在Java中,我们可以使用PowerMockito的MockStatic(SomeClass.class)来验证在测试方法中调用了静态方法。 PowerMock在Kotlin失去了魔力。
为了进行测试,我创建了以下类。
public class DummyJava {
static public Void staticMechod(){
System.out.print("Dummy method is called");
return null;
}
}
class DummyCompanion {
companion object {
fun someCompanionMethod(){
System.out.printf("companion method is called\n")
}
}
}
现在有另一个类叫DummyCompanion.someCompanion
public class DummyWrapper {
public void callAStaticMethod(){
Dummy.staticMechod();
}
public void callCompanionMethod(){
DummyCompanion.Companion.someCompanionMethod();
}
}
要进行单元测试callAStaticMethod()
,我们使用了以下
@RunWith(PowerMockRunner.class)
@PrepareForTest({Dummy.class, DummyCompanion.Companion.class})
public class staticClassTest {
//This case works
@Test
public void testForStaticMethod() {
PowerMockito.mockStatic(Dummy.class);
DummyWrapper testObject = new DummyWrapper();
Mockito.when(Dummy.staticMechod()).thenCallRealMethod();
testObject.callAStaticMethod();
PowerMockito.verifyStatic(Dummy.class);
Dummy.staticMechod();
}
//This case doesn't work. It always passes.
@Test
public void testForCompanionMethod() {
PowerMockito.mockStatic(DummyCompanion.Companion.class);
DummyWrapper testObject = new DummyWrapper();
testObject.callCompanionMethod();
PowerMockito.verifyStatic(DummyCompanion.Companion.class,Mockito.times(1));
DummyCompanion.Companion.someCompanionMethod();
}
我的问题是如何验证伴随方法的调用。
答案 0 :(得分:2)
解决方案1:在调用类中添加一个调用者函数
public class DummyWrapper {
val foo get() = DummyCompanion.Companion
public void callAStaticMethod(){
foo.staticMechod();
}
public void callCompanionMethod(){
foo.someCompanionMethod();
}
}
在测试类中,我们可以使用Mockito为get()
函数提供一个存根,并验证它是否被调用。
@Test
fun testCase{
....
val mockCompanionObj: DummyCompanion.Companion = mock()
val wrapper = DummyWrapper()
whenever(wrapper.foo).thenReturn(mockCompanionObj)
wrapper.callCompanionMethod()
verify(mockCompanionObj).someCompanionMethod()
....
}
解决方案2:使用Mockk 在Mockk中模拟伴侣对象很容易。无需在源代码中插入测试接口对象。
@Test
fun testCompanionObject() {
//Mock the companion object
mockkObject(DummyCompanion.Companion)
//define the stubbing bechavior of a companion object method
every { DummyCompanion.Companion.companionMethod() } answers { stubMethod() }
val testObject = DummyWrapper()
//Call a method that calls the companion object method
//You can verify stubMethod() is called
testObject.callCompanionMethod()
verify(exactly = 1) { DummyCompanion.someCompanionMethod() }
}
有关详细信息,请参见Mockk
答案 1 :(得分:1)
这是又一个不需要Mockk或PowerMock的解决方案。
helper
)。现在可以在单元测试中正常模拟它了。interface IStaticHelper {
fun foo(): String
fun bar(): String
}
class StaticHelper {
companion object : IStaticHelper {
override fun foo() = "foo"
override fun bar() = "bar"
}
}
class Caller(private val helper: IStaticHelper = StaticHelper.Companion) {
fun callsTheHelper(): String {
return helper.foo()
}
}
class CallerTest {
@Test
fun testCallsTheHelper() {
val helper = mock()
val caller = Caller(helper)
assertThat(caller.callsTheHelper()).isEqualTo("foo")
}
}
在这种情况下,确实是调用者不再进行静态方法调用,而其他类可以继续不变。
答案 2 :(得分:0)
您也可以使用PowerMock这样做,就像这样:
@RunWith(PowerMockRunner.class)
@PrepareForTest({DummyCompanion.class})
public class staticClassTest {
@Test
public void testForCompanionMethod() {
PowerMockito.mockStatic(DummyCompanion.class);
DummyCompanion.Companion companionMock = PowerMockito.mock(DummyCompanion.Companion.class);
Whitebox.setInternalState(
DummyCompanion.class, "Companion",
companionMock
);
DummyWrapper testObject = new DummyWrapper();
testObject.callCompanionMethod();
Mockito.verify(companionMock,Mockito.times(1)).someCompanionMethod();
}
}
Kotlin为Java(在这种情况下为Kotlin类,在DummyCompanion
中)创建了名为Companion
的Companion子类的静态字段,可以使用PowerMock的WhiteBox.setInternalState
工具将其设置为一个模拟的Companion
实例,您以后可以验证对其进行调用的方法。