Mockito mock在尝试存根包保护方法时调用实际方法实现

Jak*_*lsh 28 java 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我试图模拟的方法看起来像这样.没有最终的方法或类.

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) {
           ...     
        }
    }
Run Code Online (Sandbox Code Playgroud)

我传递模拟的类看起来像这样:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

导致实际实现被调用的原因是什么?如何防止它?

jhe*_*cks 23

Mockito代码无法访问您正在模拟的方法.

因为您的测试代码和您测试的代码在同一个包中,编译器允许您以这种方式设置模拟,但在运行时,Mockito库必须尝试访问moveAttachment,但它不适用于您的情况.这似乎是Mockito中的一个错误已知限制,因为它应该支持这种情况,(事实上,在大多数情况下确实支持它).

最简单的moveAttachment方法是制作一个公共方法.如果这不是一个选项,那么首先询问你是否想要模拟它.如果真正的方法被调用会发生什么?

最后一个选项是使用PowerMockmoveAttachment方法视为私有方法并以此方式进行模拟.