【问题标题】:Mock an object inside a method in JUnit在 JUnit 的方法中模拟对象
【发布时间】:2018-01-12 00:36:43
【问题描述】:

我正在尝试掌握 JUnit 和 Mockito 等。

我目前有以下行的方法。

ObjectMetadata metadata = getMetadata(path.toString());

有什么办法可以模拟它吗?我已经尝试过类似下面的事情

Whitebox.setInternalState(<mock of class>, "metadata", "abc");

但我只是明白了

org.powermock.reflect.exceptions.FieldNotFoundException:在 com.amazonaws.services.s3.model.ObjectMetadata 的类层次结构中找不到名为“元数据”的实例字段。

我认为这是因为以前使用 Whitebox.setInternalState 是与变量一起使用的。

任何信息。可能会帮助我入门将不胜感激。

【问题讨论】:

    标签: unit-testing junit mocking mockito


    【解决方案1】:

    如果方法受到保护,那么您不需要使用 Powermockito,普通的 Mockito 就足够了,间谍可以在这里解决问题。假设测试类与生产类在同一个包中,只是在src/test/java 目录中。

    ClassUnderTest classUnderTestSpy = Mockito.spy(new ClassUnderTest()); // spy the object 
    
    ObjectMetadata objectMetadataToReturn = new ObjectMetadata();
    
    doReturn(objectMetadataToReturn).when(classUnderTestSpy).get(Mockito.any(String.class));
    

    我使用any() 匹配器作为输入,但您也可以使用具体值。

    更新如果您看不到该方法,那么您需要创建一个扩展 prod 的内部类,实现 get 方法:

    public class Test{
    
      ObjectMetadata objectMetadataToReturn = new ObjectMetadata();
    
      @Test
      public void test(){
          ClassUnderTestCustom classUnderTestCustom  = new ClassUnderTestCustom();
    
          // perform tests on classUnderTestCustom  
      }
    
      private class ClassUnderTestCustom extends ClassUnderTest{
    
         @Override
         public String getMetadata(String path){
            return objectMetadataToReturn ;
         }
      }
    
    }
    

    【讨论】:

    • 如果测试在不同的包中,有没有办法让它工作?我的测试在 com.in.stock.sf.col.tests 中,而生产在 com.in.stock.sf.col 中。
    • 您为什么不使用 src/main/java 进行生产,使用 /src/test/java 进行测试?然后在每个中使用相同的包结构?
    • 对不起,我应该清楚的。 com.in.stock.sf.col 位于 src/main/java 中,com.in.stock.sf.col.tests 位于 /src/test/java 中。至于为什么子级别不同,我不确定,因为它是别人设置的。
    • 理论上你的 Test 可以扩展 prod 类,你将可以访问该方法。不过,正确的结构仍然是要走的路..
    • 基本上如果你想保持这种结构然后检查我的更新
    【解决方案2】:
    @PrepareForTest(ObjectMetadata.class)
    public class PowerMockDemoTest {
    
        private ObjectMetadata objectMetadata;
    
        @Before
        public void setUp() {
            objectMetadata = new ObjectMetadata();
        }
    
        @Test
        public void testMockNew() throws Exception {
            ObjectMetadata mockObjectMetadata = mock(ObjectMetadata.class);
    
            PowerMockito.whenNew(ObjectMetadata.class)
                .withAnyArguments().thenReturn(mockObjectMetadata);
    
            ObjectMetadata actualObjectmetadata = getMetadata(path.toString());
    
            assertThat(actualObjectmetadata, is(mockObjectMetadata));
        }
    }
    

    【讨论】:

    • 谢谢桑维特。 getMetadata() 受保护的事实是否会改变任何事情?我收到一条错误消息,提示“无法查看受保护的方法”。
    • 如果方法 getMetadata() 是受保护的方法,那么我们需要在 junit 中使用反射 API 来调用该方法,如下例所示: Class> clazz = mockObjectMetadata.getClass(); Method method = clazz.getDeclaredMethod("getMetadata", String.class);方法.setAccessible(true); mockObjectMetadata = (ObjectMetadata) 方法;
    猜你喜欢
    • 2021-05-21
    • 2014-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多