Mocking Chained calls in Concrete Class Mockito

|▌冷眼眸甩不掉的悲伤 提交于 2019-12-24 09:36:37

问题


I am using Mockito services to test the Exception that could be thrown in MyFinalClass and be caught in MyAbstractClass as the concrete method makes a call to the getObject method in MyFinalClass.

Please see below code.

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{
    ....
}

Below is the test class I have written. Unfortunately I am having issues with Mockito.when(myFinalClass).getObject(name).thenReturn(Mockito.mock(Object.b)), as it does not seem to get called.


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

}

Because the implementation has not yet been completed for the getObject(String name) method in MyFinalClass, I am throwing new MyException() on the call of the getObject method. However the exception does not get thrown as the Mockito.when(...) call does not get called, causing Assertion to fail.

Please help. Thank you.


回答1:


Mockito is not able to mock out final classes. There are a few ways to get around this.

1) In MyAbstractClass consider not referencing a final class, and instead reference an interface or abstract class that MyFinalClass implements (or extends). So lets say that MyFinalClass implements an interface called MyGettableApi. Then MyAbstractClass would look like this.

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

Now in your test code you can mock out MyGettableApi, since it is not final, without a problem.

    @Mock
    MyGettableApi myFinalClass;

2) Another way around this is wrap the call to myFinalClass.getObject(name); wrapped in another method.

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

}

Now in your test code you would @Spy the instance of MyAbstractClass that is being tested.

@InjectMocks
@Spy
ExampleConcreteClass exampleConcreteClass;

then you can mock out our new wrapper method.

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


来源:https://stackoverflow.com/questions/45891213/mocking-chained-calls-in-concrete-class-mockito

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!