我正在编写单元测试的方法有一个方法调用,它引用一个方法在另一个类中,它是一个抽象类。该方法是递归调用的,当我执行我的测试用例时,它会产生堆栈溢出错误。
以下是测试中的方法
public void configure(Hashtable config) throws PipeBrokenException
{
// Configure the Pipe Element ...
_source = (String) config.get(this.IMAGE_SOURCE);
_destination = (String) config.get(this.IMAGE_DESTINATION);
_printer = (XrayPrinterIf) config.get(this.PRINTER_INTERFACE);
_configProvider = (AutoPrintConfigProvider) config.get(this.AUTOPRINT_CONFIG_PROVIDER);
TraceLogger.getApplicationLogger().info("AutoPrintEndPoint Configure.. useTaskManager = " +useTaskManager);
if(useTaskManager)
{
mgr = new AutoPrintTaskManager(this);
}
super.configure(config);//this method call gives a stack overflow error, when I comment this my test case runs fine.
}
下面是方法调用super.configure(config);
的定义,包含此方法的类是一个抽象类,并且这个方法被无休止地递归调用,给出了堆栈溢出错误。
此方法在public abstract class AnAbstractClass
public abstract class AnAbstractClass{
public void configure(Hashtable properties) throws PipeBrokenException
{
if( _nextNode != null)
{
_nextNode.configure(properties);
}
}
}
这是我的JUnit测试用例,我仍然是业余爱好者并且学习,请随时在我错误的地方纠正我,并希望解决我所面临的错误。
@InjectMocks
AutoPrintEndPoint autoPrintEndPoint = PowerMockito.spy(new AutoPrintEndPoint("pipeName")); //AutoPrintEndPoint is the class under test
@Test
public void testConfigureHashtable() throws PipeBrokenException
{
// SmartPipeNode node=Mockito.mock(SmartPipeNode.class,Mockito.CALLS_REAL_METHODS);
AutoPrintConfigProvider autoPrintConfigProvider=Mockito.mock(AutoPrintConfigProvider.class); //AutoPrintConfigProvider is an interface
XrayPrinterIf _printerIf=Mockito.mock(XrayPrinterIf.class);//XrayPrinterIf is an interface
Hashtable config=new Hashtable();
config.put(AutoPrintEndPoint.IMAGE_SOURCE,"Source");
config.put(AutoPrintEndPoint.IMAGE_DESTINATION,"Destination");
config.put(AutoPrintEndPoint.PRINTER_INTERFACE,_printerIf);
config.put(AutoPrintEndPoint.AUTOPRINT_CONFIG_PROVIDER,autoPrintConfigProvider);
autoPrintEndPoint.configure("useTaskManager","yes");
//Mockito.doNothing().when(autoPrintEndPoint).configure(config);
autoPrintEndPoint.configure(config);
String _source=Whitebox.getInternalState(autoPrintEndPoint, "_source");
String _destination=Whitebox.getInternalState(autoPrintEndPoint, "_destination");
System.out.println(_destination+"hello destination");
System.out.println(_source+"here");
}
堆栈跟踪
java.lang.StackOverflowError
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.access$100(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at org.powermock.core.classloader.MockClassLoader.loadModifiedClass(MockClassLoader.java:178)
at org.powermock.core.classloader.DeferSupportingClassLoader.loadClass(DeferSupportingClassLoader.java:68)
at java.lang.ClassLoader.loadClass(Unknown Source)
答案 0 :(得分:1)
由于您使用的是PowerMockito,因此您应该能够禁止对AnAbstractClass中方法的任何调用:
PowerMockito.suppress(MemberMatcher.methodsDeclaredIn(AnAbstractClass.class));
答案 1 :(得分:0)
_nextNode
是指this
。
添加支票:
if (_nextNode != null && _nextNode != this) {
_nextNode.configure(properties);
}
如果可以使用循环链接,则必须跟踪集合中访问的所有节点,并检查您是否再次访问节点。
答案 2 :(得分:0)
我创建了一个线程来控制递归调用的次数。在线程中,我使用类的模拟对象设置变量_nextNode
,该类扩展了包含递归方法的抽象类。调用该方法指定的次数后,变量_nextNode
将设置为null。我希望这个答案有用。
下面是我编写的代码片段,用于纠正我的情况下的堆栈溢出错误
AutoPrintEndPoint autoPrintEndPointMock = Mockito.mock(AutoPrintEndPoint.class);
new Thread() {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
autoPrintEndPoint.setNextNode(autoPrintEndPointMock);
}
autoPrintEndPoint.setNextNode(null);
}
}.start();
autoPrintEndPoint.configure(config);