Reputation: 119
The method I am writing unit test for has a method call that refers to a method In another class which is an abstract class. That method is called recursively, which is giving a stack overflow error when I execute my test case.
Below is the method under test
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.
}
Below is the definition of the method call super.configure(config);
, the class containing this method is an abstract class, and this method is called recursively endlessly giving me stack over flow error.
This method defined in public abstract class AnAbstractClass
public abstract class AnAbstractClass{
public void configure(Hashtable properties) throws PipeBrokenException
{
if( _nextNode != null)
{
_nextNode.configure(properties);
}
}
}
This is my JUnit test case, I am still an amateur at this and learning, please feel free to correct me wherever I am wrong and hopefully resolve the error I am facing.
@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");
}
Stack Trace
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)
Upvotes: 1
Views: 2188
Reputation: 119
I created a thread to control the number of times the recursive call is taking place. and within the thread I have set the variable _nextNode
with the mock object of the class which extends the abstract class that contains the recursive method. After the method is called the number of times specified then the variable _nextNode
is set to null. I hope this answer will be useful.
below is the piece of code that I wrote to rectify the stack overflow error in my case
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);
Upvotes: 0
Reputation: 9622
Since you are using PowerMockito you should be able to suppress any calls to methods in AnAbstractClass with:
PowerMockito.suppress(MemberMatcher.methodsDeclaredIn(AnAbstractClass.class));
Upvotes: 1
Reputation: 425073
_nextNode
refers to this
.
Add a check:
if (_nextNode != null && _nextNode != this) {
_nextNode.configure(properties);
}
If circular links are possible, you'll have to keep track of all nodes visited in a Set and check that you're not visiting a node again.
Upvotes: 0