代码之家  ›  专栏  ›  技术社区  ›  mashimarro

在具体类Mockito中模拟链式调用

  •  1
  • mashimarro  · 技术社区  · 7 年前

    public abstract class MyAbstractClass{
    
        @Autowired
        private MyFinalClass myFinalClass;
    
        //concrete method
        protected Object myConcreteMethod(String name){
            try{
                Object b = myFinalClass.getObject(name);
                return b;
            } catch(MyException e){
              LOGGER.log("ERROR THROWN" + e);
            }
        }
    
    }
    

    public final class MyFinalClass {
    
        public Object getObject(String name) throws MyException{
            **** HAS NOT YET BEEN IMPLEMENTED ****
            return null;
        }
    
    }
    

    public MyException extends Exception{
        ....
    }
    

    下面是我写的测试类。不幸的是,我和莫基托有问题。when(myFinalClass)。getObject(名称)。然后返回(Mockito.mock(Object.b)),因为它似乎没有被调用。


    @ContextConfiguration(locations = "classpath:applicationContext-test.xml")
    @RunWith(PowerMockRunner.class)
    public class MyAbstractClassTest  {
    
        public static class ExampleConcreteClass extends MyAbstractClass{
    
        }
    
        @InjectMocks
        ExampleConcreteClass exampleConcreteClass;
    
        @Mock
        MyFinalClass myFinalClass;
    
        @Before
        public void setUp(){
            MockitoAnnotations.initMocks(this);
        }
    
        @Test
        public void testMyConcreteMethod(){
            try{
               Mockito.when(myFinalClass).getObject(name). 
               thenThrow(new MyException()); 
    
               exampleConcreteClass.myConcreteMethod();
               Assert.fail();
            }catch(MyException e){
               Assert.assertTrue(Boolean.TRUE);
            }
        }
    
    }
    

    请帮忙。非常感谢。

    1 回复  |  直到 7 年前
        1
  •  2
  •   Jose Martinez    7 年前

    Mockito无法模拟最终类。有几种方法可以解决这个问题。

    1) 在 MyAbstractClass MyFinalClass 实现(或扩展)。这么说吧 我的最终课程 实现一个名为 MyGettableApi . 然后 MyAbstractClass

     public abstract class MyAbstractClass{
    
        @Autowired
        private MyGettableApi gettableService;
    
        //concrete method
        protected Object myConcreteMethod(String name){
            try{
                Object b = gettableService.getObject(name);
                return b;
            } catch(MyException e){
              LOGGER.log("ERROR THROWN" + e);
            }
        }
    
    }  
    
    
    public final class MyFinalClass implements MyGettableApi {
    
        @Override
        public Object getObject(String name) throws MyException{
            **** HAS NOT YET BEEN IMPLEMENTED ****
            return null;
        }
    
    }
    
    
    public interface MyGettableApi {
        public Object getObject(String name);
    }
    

    现在,在测试代码中,您可以模拟 MyGettableApi

        @Mock
        MyGettableApi myFinalClass;
    

    2) 另一种解决方法是结束通话 myFinalClass.getObject(name); 用另一种方法包装。

    public abstract class MyAbstractClass{
    
        @Autowired
        private MyFinalClass myFinalClass;
    
        //concrete method
        protected Object myConcreteMethod(String name){
            try{
                Object b = myGetObjectWrapperMethod(name);
                return b;
            } catch(MyException e){
              LOGGER.log("ERROR THROWN" + e);
            }
        }
    
        Object myGetObjectWrapperMethod(String name) {
            return myFinalClass.getObject(name);
        }
    
    }
    

    现在在测试代码中 @Spy 的实例 MyAbstractClass

    @InjectMocks
    @Spy
    ExampleConcreteClass exampleConcreteClass;
    

    然后您可以模拟我们的新包装器方法。

    doThrow(new MyException()).when(exampleConcreteClass).myGetObjectWrapperMethod(name);