在具体的类Mockito中模拟链接的呼叫 [英] Mocking Chained calls in Concrete Class Mockito

查看:91
本文介绍了在具体的类Mockito中模拟链接的呼叫的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Mockito服务来测试可能在MyFinalClass中引发并在MyAbstractClass中捕获的异常,因为具体方法在MyFinalClass中调用了getObject方法.

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.

请参见下面的代码.

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

下面是我编写的测试课程.不幸的是,我遇到了Mockito.when(myFinalClass).getObject(name).thenReturn(Mockito.mock(Object.b))的问题,因为它似乎没有被调用.

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

}


由于MyFinalClass中的getObject(String name)方法的实现尚未完成,因此在调用getObject方法时抛出了新的MyException().但是,由于未调用Mockito.when(...)调用,因此不会引发异常,从而导致断言失败.


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.

请帮助.谢谢.

推荐答案

Mockito无法模拟最终课程.有几种方法可以解决此问题.

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

1)在MyAbstractClass中,请考虑不引用最终类,而是引用MyFinalClass实现(或扩展)的接口或抽象类.因此,可以说MyFinalClass实现了一个名为MyGettableApi的接口.然后MyAbstractClass看起来像这样.

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

现在,您可以在测试代码中模拟MyGettableApi,因为它不是最终版本,没有问题.

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

    @Mock
    MyGettableApi myFinalClass;

2)解决此问题的另一种方法是将对myFinalClass.getObject(name);的调用包装在另一个方法中.

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

}

现在,在测试代码中,您将@Spy被测试的MyAbstractClass实例.

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

这篇关于在具体的类Mockito中模拟链接的呼叫的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆