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

2022-09-01 07:01:44

我试图使用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) {
           ...     
        }
    }

我通过模拟的类看起来像这样:

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;
    }
}

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


答案 1

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

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

最简单的办法是制作一个公共方法。如果这不是一种选择,那么首先要问你是否想嘲笑它。如果调用真正的方法会发生什么?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
  • 朱尼特-4.10.jar
  • mockito-all-1.9.0.jar
  • javassist-3.16.1-GA.jar
  • 淫秽-1.2.jar
  • hamcrest-core-1.1.jar

推荐