doNothing.When для самого метода private void вызывает метод

Я пытаюсь протестировать один из моих классов с именем Store, и, в частности, метод с именем removeFromFavourite ниже — это метод

    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, а затем создал шпиона из объекта хранилища и назначил его обратно самому объекту хранилища.

Ниже приведен метод тестирования для removeFromFavourite.

@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", и я получаю незавершенное исключение Mocking

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)

Любая идея, где я ошибаюсь?


person Kumar Gaurav    schedule 30.04.2019    source источник


Ответы (2)


Я думаю, что третий аргумент в when должен быть сопоставлением mockito:

PowerMockito.doNothing().when(store, "deleteObject", eq(mockedObject));
person matanper    schedule 30.04.2019

Mockito предоставляет метод doNothing() для имитации вызовов метода void. Для приведенного выше вопроса метод void deleteFromRealm можно высмеять как

Mockito.doNothing().when(mockedObject).deleteFromRealm();

Поскольку deleteFromRealm является окончательным и не может быть имитирован. Чтобы имитировать метод deleteObject того же класса

ClassToBeTested testClass = new ClassToBeTested();
ClassToBeTested testClassSpy = PowerMockito.spy(testClass);
PowerMockito.doNothing().when(testClassSpy, "deleteObject", mockedRealm);
person singh30    schedule 01.05.2019
comment
Привет! Хотя этот фрагмент кода может быть решением, включение объяснения действительно помогает улучшить качество вашего поста. Помните, что вы отвечаете на вопрос для будущих читателей, и эти люди могут не знать причин вашего предложения кода. - person Wing; 01.05.2019
comment
Я вызвал deleteFromRealm из другого приватного метода, потому что deleteFromRealm является окончательным и не может быть высмеян. Следовательно, я ищу имитацию вызова частного метода deleteObject - person Kumar Gaurav; 02.05.2019