简体   繁体   English

具体类Mockito中的模拟链接的呼叫

[英]Mocking Chained calls in Concrete Class Mockito

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. 我正在使用Mockito服务来测试可能在MyFinalClass中引发并在MyAbstractClass中捕获的异常,因为具体方法在MyFinalClass中调用了getObject方法。

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. 不幸的是,我遇到了Mockito.when(myFinalClass).getObject(name).thenReturn(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);
        }
    }

}

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. 因为MyFinalClass中的getObject(String name)方法的实现尚未完成,所以我在getObject方法的调用上抛出了新的MyException()。 However the exception does not get thrown as the Mockito.when(...) call does not get called, causing Assertion to fail. 但是,由于未调用Mockito.when(...)调用,因此不会引发异常,从而导致断言失败。

Please help. 请帮忙。 Thank you. 谢谢。

Mockito is not able to mock out final classes. Mockito无法模拟最终课程。 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). 1)在MyAbstractClass考虑不引用最终类,而应引用MyFinalClass实现(或扩展)的接口或抽象类。 So lets say that MyFinalClass implements an interface called MyGettableApi . 因此,可以说MyFinalClass实现了一个名为MyGettableApi的接口。 Then MyAbstractClass would look like this. 然后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);
}

Now in your test code you can mock out MyGettableApi , since it is not final, without a problem. 现在,在您的测试代码中,您可以模拟MyGettableApi ,因为它不是最终的,没有问题。

    @Mock
    MyGettableApi myFinalClass;

2) Another way around this is wrap the call to myFinalClass.getObject(name); 2)解决此问题的另一种方法是包装对myFinalClass.getObject(name);的调用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. 现在,在您的测试代码中,您将@Spy正在测试的MyAbstractClass实例。

@InjectMocks
@Spy
ExampleConcreteClass exampleConcreteClass;

then you can mock out our new wrapper method. 那么您可以模拟出我们的新包装方法。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM