Reputation: 63
When the method is running I would like to throw an exception (while testing). I could do few things:
- stub(mock.someMethod("some arg")).toThrow(new RuntimeException());
- when(mock.someMethod("some arg")).thenThrow(new RuntimeException())
- doThrow.....
Usually I create a spy object to call spied method. Using stubbing I can throw an exception. This exception is always monitored in log. More importantly is that the test does not crash because the method where the exception was thrown could catch it and return specific value. However, in the code bellow exception is not thrown (nothing is monitored in the log && return value is true but should be false).
Issues: In this case the exception is not thrown:
DeviceInfoHolder deviceInfoHolder = new DeviceInfoHolder();
/*Create Dummy*/
DeviceInfoHolder mockDeviceInfoHolder = mock (DeviceInfoHolder.class);
DeviceInfoHolderPopulator deviceInfoHolderPopulator = new DeviceInfoHolderPopulator();
/*Set Dummy */
deviceInfoHolderPopulator.setDeviceInfoHolder(mockDeviceInfoHolder);
/*Create spy */
DeviceInfoHolderPopulator spyDeviceInfoHolderPopulator = spy(deviceInfoHolderPopulator);
/*Just exception*/
IllegalArgumentException toThrow = new IllegalArgumentException();
/*Stubbing here*/
stub(spyDeviceInfoHolderPopulator.populateDeviceInfoHolder()).toThrow(toThrow);
/*!!!!!!Should be thrown an exception but it is not!!!!!!*/
boolean returned = spyDeviceInfoHolderPopulator.populateDeviceInfoHolder();
Log.v(tag,"Returned : "+returned);
Upvotes: 3
Views: 3379
Reputation: 24561
Creating new answer, because spyDeviceInfoHolderPopulator.populateDeviceInfoHolder(); is your testing method.
One of the basic rules of unit testing is that your shouldn't stub on testing method, because you want to test it's behavior. You may want to stub methods of faked dependencies of test class with Mockito.
So in this case, you probably want to remove the spy, call your testing method and as last stage of your test (that is missing currently), you should verify if logic in testing method was correct.
EDIT:
After last comment it is finally clear to me what logic you are testing. Let say that your testing object has dependency on some XmlReader. Also immagine that this reader has method called "readXml()" and is used in your testing logic for reading from XML. My test would look like this:
XmlReader xmlReader = mock (XmlReader.class);
mock(xmlReader.readXml()).doThrow(new IllegalArgumentException());
DeviceInfoHolderPopulator deviceInfoHolderPopulator = new DeviceInfoHolderPopulator(xmlReader);
//call testing method
boolean returned = spyDeviceInfoHolderPopulator.populateDeviceInfoHolder();
Assign.assignFalse(returned);
Upvotes: 1
Reputation: 6855
The creation of spy object is bad here.
The creation should be like
DeviceInfoHolderPopulator spyDeviceInfoHolderPopulator = spy(new DeviceInfoHolderPopulator());
then stub your methods on the spy object.
Reference : API
EDIT:
This is from API.
Sometimes it's impossible or impractical to use Mockito.when(Object) for stubbing spies.
Therefore for spies it is recommended to always
use doReturn|Answer|Throw()|CallRealMethod family of methods for stubbing.
Example:
List list = new LinkedList();
List spy = spy(list);
//Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)
when(spy.get(0)).thenReturn("foo");
//You have to use doReturn() for stubbing
doReturn("foo").when(spy).get(0);
Upvotes: 0
Reputation: 24561
There is slightly different syntax for spy:
doThrow(toThrow).when(spyDeviceInfoHolderPopulator).populateDeviceInfoHolder();
Read more in section "Important gotcha on spying real objects!" here: https://mockito.googlecode.com/svn/tags/latest/javadoc/org/mockito/Mockito.html#13
Upvotes: 1