在具体的类Mockito中模拟链接的呼叫 [英] Mocking Chained calls in Concrete Class 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屋!