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

我正在尝试使用Mockito 1.8.5存根方法,但这样做会调用真正的方法实现(使用“”作为parm值)会引发exception。

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

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

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

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

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

最后一个选项是使用PowerMock将moveAttachment方法视为私有方法并以此方式进行模拟。

我不同意公认的回应。

我想,您必须提供有关您的环境的更多详细信息。 我无法重现你的问题。 我在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-ALL-1.9.0.jar
  • Javassist进行-3.16.1-GA.jar
  • objenesis-1.2.jar
  • hamcrest核-1.1.jar