我正在尝试测试一个名为 Store 的类,特别是一个名为 removeFromFavorite 的方法以下是方法
public void removeFromFavourite(Quote quote) {
if(quote == null) {
throw new IllegalArgumentException("Quote can't be null");
}
if (quote.getId() <1) {
throw new IllegalArgumentException("Quote id can't be less than 1");
}
realm.beginTransaction();
QuoteRealMObject object = realm.where(QuoteRealMObject.class).
equalTo(QuoteRealMObject.ID, quote.getId()).findFirst();
if(object != null) {
deleteObject(object);
}
realm.commitTransaction();
}
private void deleteObject(RealmObject object) {
object.deleteFromRealm();
}
我创建了 deleteObject 方法来调用 deleteFromRealm,因为 deleteFromRealm 是最终的,因此我无法模拟它。
我的期望是通过创建其间谍来模拟对"deleteObject"ob Store对象的调用
这是我@Before
方法
private Realm mockedRealm;
private Store store;
@Before
public void setUp() throws Exception {
mockedRealm = Mockito.mock(Realm.class);
store = new Store(mockedRealm);
store = PowerMockito.spy(store);
}
因此,我创建了一个 Realm 的模拟对象,并使用它来创建类 Store 的对象,然后从存储的对象中创建了一个间谍,并将其分配回存储对象本身。
以下是从收藏夹中删除的测试方法
@Test
public void removeFromFavourite() throws Exception {
Quote quot = new Quote();
quot.setId(1);
RealmQuery<QuoteRealMObject> query = Mockito.mock(RealmQuery.class);
RealmQuery<QuoteRealMObject> filteredQuery = Mockito.mock(RealmQuery.class);
Mockito.when(mockedRealm.where(QuoteRealMObject.class)).thenReturn(query);
Mockito.when(query.equalTo(QuoteRealMObject.ID, 1)).thenReturn(filteredQuery);
QuoteRealMObject mockedObject = Mockito.mock(QuoteRealMObject.class);
Mockito.when(filteredQuery.findFirst()).thenReturn(mockedObject);
PowerMockito.doNothing().when(store, "deleteObject", mockedObject);
store.removeFromFavourite(quot);
}
这是PowerMockito.doNothing().when(store, "deleteObject", mockedObject);
行本身调用真正的私有方法"deleteObject"我正在未完成 嘲笑异常
org.mockito.exceptions.misusing.UnfinishedStubbingException:
Unfinished stubbing detected here:
-> at com.kgcorner.vachan.io.StoreTest.removeFromFavourite(StoreTest.java:132)
E.g. thenReturn() may be missing.
Examples of correct stubbing:
when(mock.isOk()).thenReturn(true);
when(mock.isOk()).thenThrow(exception);
doThrow(exception).when(mock).someVoidMethod();
Hints:
1. missing thenReturn()
2. you are trying to stub a final method, which is not supported
3: you are stubbing the behaviour of another mock inside before 'thenReturn' instruction if completed
at org.mockito.internal.runners.DefaultInternalRunner$1$1.testFinished(DefaultInternalRunner.java:70)
at org.junit.runner.notification.SynchronizedRunListener.testFinished(SynchronizedRunListener.java:56)
at org.junit.runner.notification.RunNotifier$7.notifyListener(RunNotifier.java:190)
at org.junit.runner.notification.RunNotifier$SafeNotifier.run(RunNotifier.java:72)
at org.junit.runner.notification.RunNotifier.fireTestFinished(RunNotifier.java:187)
at org.junit.internal.runners.model.EachTestNotifier.fireTestFinished(EachTestNotifier.java:38)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:331)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.mockito.internal.runners.DefaultInternalRunner$1.run(DefaultInternalRunner.java:79)
at org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:85)
at org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:39)
at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:163)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
知道吗,我错在哪里?
我认为when
中的第三个参数应该是一个模拟匹配器:
PowerMockito.doNothing().when(store, "deleteObject", eq(mockedObject));
Mockito提供了一个方法doNothing((来模拟对void方法的调用。对于上面的问题,void 方法 deleteFromRealm 可以像
Mockito.doNothing().when(mockedObject).deleteFromRealm();
因为 deleteFromRealm 是最终的,不能被嘲笑。模拟方法删除同一类的对象
ClassToBeTested testClass = new ClassToBeTested();
ClassToBeTested testClassSpy = PowerMockito.spy(testClass);
PowerMockito.doNothing().when(testClassSpy, "deleteObject", mockedRealm);
也许有点太晚了,但您的问题的可能解决方案可能如下所示:
PowerMockito.doNothing().when(store, "deleteObject", Matchers.any(RealmObject.class));
亲切问候
测试类的注释中添加模拟类PrepareForTest
以实际准备 powermockito 来模拟私有方法
public class A{
private void deleteObject(RealmObject object) {
object.deleteFromRealm();
}
}
@RunWith(PowerMockRunner.class)
@PrepareForTest(A.class)
public class ATest{
@Spy
A mock;
@Test
public void test(){
PowerMockito.doNothing().when(mock, method(TaskReqImpl.class,"deleteObject", RealmObject .class));
// OR
PowerMockito.doNothing().when(mock, "deleteObject", any());
}