我正在使用Mockito服务来测试可能在MyFinalClass2中抛出的异常并在MyAbstractClass中捕获,因为具体方法调用了MyFinalClass2中的getValue方法。此方法返回一个接口(MyInterfaceClass)对象。
我之前在Mocking Chained calls in Concrete Class Mockito中提出了一个问题,谢天谢地,提供的解决方案在调用MyFinalClass中的getObject方法时起作用。因此,test1有效!
但是,这次我有另一个不是@Autowired的最终类(MyFinalClass2),并且在调用MyFinalClass中的方法之后调用。 MyFinalClass2类型的Object是从第一次调用MyFinalClass中的方法返回的。在test2中手动抛出MyException2时,它不会被识别,因此在Test2中导致AssertionFailure。
另请注意,下面的代码行返回NULL,因为它尚未实现。这就是为什么我在调用此方法时在Test2中返回MyFinalClass2的新实例的原因。
MyFinalClass2 myFinalClass2 = getObject(strName);
请参阅以下代码。
public abstract class MyAbstractClass{
@Autowired
private MyFinalClass myFinalClass;
//concrete method
protected MyInterfaceClass myConcreteMethod(String strName, String str)
{
try{
//returns null as it has not yet been implemented
MyFinalClass2 myFinalClass2 = getObject(strName);
MyInterfaceClass b = getValue(myFinalClass2,str);
return b;
} catch(MyException e){
LOGGER.log("ERROR THROWN" + e);
} catch(MyException2 e){
LOGGER.log("ERROR THROWN" + e);
}
}
public MyFinalClass2 getObject(String strName){
return myFinalClass.getObject(strName);
}
public MyInterfaceClass getValue(MyFinalClass2 myFinalClass2, String
str){
return myFinalClass2.getValue(str);
}
}
public final class MyFinalClass {
public MyFinalClass2 getObject(String strName) throws MyException{
**** HAS NOT YET BEEN IMPLEMENTED ****
return null;
}
}
public final class MyFinalClass2 {
public MyInterfaceClass getValue(String str) throws MyException2{
**** HAS NOT YET BEEN IMPLEMENTED ****
return null;
}
}
public interface MyInterfaceClass {
**** HAS NOT YET BEEN IMPLEMENTED BY ANY CLASS ****
void getStuff();
}
@ContextConfiguration(locations = "classpath:applicationContext-test.xml")
@RunWith(PowerMockRunner.class)
public class MyAbstractClassTest {
public static class ExampleConcreteClass extends MyAbstractClass{
}
@InjectMocks
@Spy
ExampleConcreteClass exampleConcreteClass;
@Before
public void setUp(){
MockitoAnnotations.initMocks(this);
}
//THIS WORKS --- TEST 1
@Test
public void testIfExceptionOneIsThrown(){
try{
Mockito.when(exampleConcreteClass).getObject(name).
thenThrow(new MyException());
exampleConcreteClass.myConcreteMethod();
Assert.fail();
}catch(MyException e){
Assert.assertTrue(Boolean.TRUE);
}
}
//This test DOES NOT work --- TEST 2
@Test
public void testIfExceptionTwoIsThrown(){
try{
MyFinalClass2 myFinClass2 = new MyFinalClass2();
String strName = "name";
String str = "str";
Mockito.when(exampleConcreteClass).getValue(myFinClass2,str).
thenThrow(new MyException2());
Mockito.when(exampleConcreteClass).getObject(strName).
thenReturn(myFinClass2);
exampleConcreteClass.myConcreteMethod();
Assert.fail();
}catch(MyException e){
Assert.fail();
}catch(MyException2 e){
Assert.assertTrue(Boolean.TRUE);
}
}
}
请帮忙。非常赞赏!
答案 0 :(得分:3)
首先,我很遗憾地这么说,但如果你需要认真考虑测试,通常肯定是代码不好。不管怎么说,你不需要PowerMock,因为Mockito 2已经能够mock final classes了(不过你必须选择加入)。
此外,您的测试完全没有任何意义,因为exampleConcreteClass.myConcreteMethod()
无法抛出MyException2
,因为......
} catch(MyException2 e){
LOGGER.log("ERROR THROWN" + e);
}
...因此MyException2
将永远不会离开方法的范围,但会转换为日志消息然后被丢弃。它不会离开方法,因此试图断言它将不起作用。你也会有throw e;
之类的东西:
} catch(MyException2 e){
LOGGER.log("ERROR THROWN" + e);
throw e; // re-throw e, otherwise it ends here
}
另外,正如一个提示,通过简单的写作,你可以更轻松地完成你想做的事情......
@Test(expected=MyException2.class)
public void testIfExceptionTwoIsThrown() throws MyException, MyException2 {
...这样,您可以从测试方法中删除所有try-catch内容,因为如果没有抛出MyException2,JUnit将自动失败测试。或者,如果你想拥有更多的控制权,你甚至可以看看JUnit的ExpectedException规则,它比expected
参数更强大,更通用(但那个应该足够了)对于这种情况)。
但是,当然,没有什么可以改变这样一个事实,即只要你的方法捕获你的MyException2,它就不会离开所述方法,因此测试它将无济于事。