Подтвердить что ты не робот

Mockito макет вызова реальной реализации метода при попытке заглушить защищенный пакет метод

Я пытаюсь заглушить метод, используя Mockito 1.8.5, но при этом вызывает реализацию реального метода (с "как значения parm" ), который генерирует исключение.

package background.internal; //located in trunk/tests/java/background/internal

public class MoveStepTest {

    @Test
    public void testMoveUpdate() {
        final String returnValue = "value";
        final FileAttachmentContainer file = mock(FileAttachmentContainer.class);
        doReturn(returnValue).when(file).moveAttachment(anyString(), anyString(), anyString());
        //this also fails
        //when(file.moveAttachment(anyString(), anyString(), anyString())).thenReturn(returnValue);

        final AttachmentMoveStep move = new AttachmentMoveStep(file);
        final Action moveResult = move.advance(1, mock(Context.class));
        assertEquals(Action.done, moveResult);
    }
}

Метод, который я пытаюсь высмеять, выглядит следующим образом. Нет окончательного метода или классов.

package background.internal; //located in trunk/src/background/internal


   public class FileAttachmentContainer {
        String moveAttachment(final String arg1, final String arg2, final String arg3) 
                throws CustomException {
            ...
        }

        String getPersistedValue(final Context context) {
           ...     
        }
    }

И класс, в котором я передаю mock, выглядит так:

package background.internal; //located in trunk/src/background/internal
public class AttachmentMoveStep {

    private final FileAttachmentContainer file;

    public AttachmentMoveStep(final FileAttachmentContainer file) {
        this.file = file;        
    }

    public Action advance(final double acceleration, final Context context) {
        try {
            final String attachmentValue = this.file.getPersistedValue(context);
            final String entryId = this.file.moveAttachment(attachmentValue, "attachment", context.getUserName());

            //do some other stuff with entryId
        } catch (CustomException e) {
            e.log(context);
        }    
        return Action.done;
    }
}

Что вызывает вызов реальной реализации и как я могу ее предотвратить?

4b9b3361

Ответ 1

Метод, в котором вы издеваетесь, недоступен для кода Mockito.

Поскольку ваш тестовый код и ваш тестируемый код находятся в одном пакете, компилятор позволяет настроить ваш макет таким образом, но во время выполнения библиотека Mockito должна пытаться получить доступ к moveAttachment, но она не работает в ваш случай. Это выглядит как ошибка или известное ограничение в Mockito, поскольку оно должно поддерживать этот случай (и на самом деле, поддерживает его в большинстве случаев).

Проще всего сделать moveAttachment общедоступный метод. Если это не вариант, то сначала задайте вопрос, хотите ли вы даже издеваться над этим. Что произойдет, если будет вызван реальный метод?

Последний вариант - использовать PowerMock для обработки метода moveAttachment в качестве частного метода и издеваться над ним таким образом.

Ответ 2

Я не согласен с принятым ответом.

Думаю, вам нужно предоставить более подробную информацию о своей среде. Я не могу воспроизвести вашу проблему. Я пишу следующий код в проекте maven:

package background.internal; //located in src/main/java

public class FileAttachmentContainer {
    String moveAttachment(String arg1, String arg2, String arg3) {
        throw new IllegalStateException();
    }

    String getPersistedValue(Context context) {
        throw new IllegalStateException();
    }
}

и

package background.internal;

public class AttachmentMoveStep {

    private FileAttachmentContainer file;

    public AttachmentMoveStep(FileAttachmentContainer file) {
        this.file = file;
    }

    public Action advance(double acceleration, Context context) {
        String attachmentValue = file.getPersistedValue(context);
        file.moveAttachment(attachmentValue, "attachment", context.getUserName());
        return Action.done;
    }
}

и следующий тестовый проход

package background.internal; //located in src/test/java

import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;

import org.junit.Test;

public class MoveStepTest {

    @Test
    public void testMoveUpdate() {
        String returnValue = "value";
        FileAttachmentContainer file = mock(FileAttachmentContainer.class);
        doReturn(returnValue).when(file).moveAttachment(anyString(), anyString(), anyString());
        //this also works
        //when(file.moveAttachment(anyString(), anyString(), anyString())).thenReturn(returnValue);

        AttachmentMoveStep move = new AttachmentMoveStep(file);
        Action moveResult = move.advance(1, mock(Context.class));
        assertEquals(Action.done, moveResult);
    }
}

В моем проекте используются следующие зависимости:

  • jdk1.7.0_05
  • JUnit-4.10.jar
  • Mockito-все-1.9.0.jar
  • Javassist-3.16.1-GA.jar
  • objenesis-1.2.jar
  • Hamcrest-ядро-1.1.jar