3

When the method is running I would like to throw an exception (while testing). I could do few things:

  1. stub(mock.someMethod("some arg")).toThrow(new RuntimeException());
  2. when(mock.someMethod("some arg")).thenThrow(new RuntimeException())
  3. 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);
Bosko Mijin
  • 3,287
  • 3
  • 32
  • 45
sergey136
  • 63
  • 1
  • 7
  • Check that your method is not final. Final methods cannot be stubbed. – Alex Sep 25 '14 at 12:29
  • possible duplicate of [Mockito: Trying to spy on method is calling the original method](http://stackoverflow.com/questions/11620103/mockito-trying-to-spy-on-method-is-calling-the-original-method) – Alex Sep 25 '14 at 12:40
  • What are you trying to achieve with this logging? If your testing method throws exception, just bubble it up and testing framework will take care of logging – luboskrnac Sep 25 '14 at 12:53
  • If the exception is thrown inside the method it will return false. – sergey136 Sep 25 '14 at 12:56
  • I want to test the return when the exception will be thrown in the method. Logging is simply for observing – sergey136 Sep 25 '14 at 12:58

3 Answers3

1

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

luboskrnac
  • 23,973
  • 10
  • 81
  • 92
  • Thank you. Using this example, the exception is thrown directly in the test while I am trying to throw it directly in the method so that the method returned different value. (Sorry if I wrote something wrong, just recently installed Mockito and started working with test doubles) – sergey136 Sep 25 '14 at 12:39
  • spyDeviceInfoHolderPopulator.populateDeviceInfoHolder(); call should throw the exception. I thought that this is the behavior you are trying to achieve – luboskrnac Sep 25 '14 at 12:51
  • It should throw an exception but this exception should not be thrown in the test case it self. Because right now I have to use try and catch otherwise the will fail – sergey136 Sep 25 '14 at 12:53
  • @sergey136 I don't get that, sorry. – luboskrnac Sep 25 '14 at 12:54
  • Look Ikrnac. I want to throw an exception in the method when I am testing it.So that if the exception is thrown the function should return different value. Lets forget about the tests for a while. For example the program is running and it started executing this function. However, the function threw an exception. I need to get a return value from it because the result from this functions depends on the result of the next function. – sergey136 Sep 25 '14 at 13:03
  • @sergey136 Is spyDeviceInfoHolderPopulator.populateDeviceInfoHolder() your testing method? – luboskrnac Sep 25 '14 at 13:05
  • With your solution the exception is thrown directly in the test method but I want to throw it in the function. – sergey136 Sep 25 '14 at 13:05
  • It is the testing method. (I recently started working with Mochito) – sergey136 Sep 25 '14 at 13:06
1

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);
luboskrnac
  • 23,973
  • 10
  • 81
  • 92
  • If you can, could you please explain how should I write this test ? – sergey136 Sep 25 '14 at 13:15
  • I can try, if you post or explain what your testing method does/should do – luboskrnac Sep 25 '14 at 13:17
  • I want simply throw an exception in this method and verify that it will return false (This method is about parsing XML file and there are lots of try-catch statements). What happens if the XML file is corrupted. In this case the method should return false. This is what I want to test. (The application is for android So I cannot use JUnit4) – sergey136 Sep 25 '14 at 13:22
  • Thank you very much Ikrnac. I fully understood what you mentioned. Instead of making spy object of the testing method it is necessary to make a spy/mock object of the class which is inside this testing method which could be anything. In this case the exception will be thrown inside the testing method. Sorry that I do not have enough rating to vote up your provided solution. – sergey136 Sep 25 '14 at 14:07
  • @sergey136 glad that I helped. BTW you can mark one of my answers as correct and that would give me 15 reputation points, thanks – luboskrnac Sep 25 '14 at 15:13
0

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);
Vinay Veluri
  • 6,671
  • 5
  • 32
  • 56
  • This is same creation of spy as in answer, just compressed into one line. – luboskrnac Sep 25 '14 at 12:34
  • @lkrnac I'm surprised. How it would be same as creating spy on new object and existing object? Updated my answer with documentation from API. It is not same. You need to use explicit methods like `doThrow` like in your answer. But what is use of creating objects where you cannot simulate the functionality of spying ? I prefer going on creating spy on new objects rather than create and then forcibly throw exception. – Vinay Veluri Sep 25 '14 at 12:41
  • @downvoter, care to comment what is wrong in the above answer ? Wont it have the correct judgement of what OP has asked or is it apart from the context or is that wrong ? I have provided API documentation which sites proof of concept. – Vinay Veluri Sep 25 '14 at 12:42
  • Well in my case doReturn will return true or false (depends what I put there). But I want throw an exception in the method from the test to observe different function return. – sergey136 Sep 25 '14 at 12:45
  • DeviceInfoHolderPopulator deviceInfoHolderPopulator = new DeviceInfoHolderPopulator(); DeviceInfoHolderPopulator spyDeviceInfoHolderPopulator = spy(deviceInfoHolderPopulator); -> this is the same as your creation – luboskrnac Sep 25 '14 at 12:46
  • @VinayVeluri I am downvoter and commented what is wrong with your answer – luboskrnac Sep 25 '14 at 12:48
  • @lkrnac, //Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty) when(spy.get(0)).thenReturn("foo"); --> what do these lines say from API ? Is that not right ? – Vinay Veluri Sep 25 '14 at 12:54
  • @VinayVeluri Sorry, don't understand your last comment – luboskrnac Sep 25 '14 at 12:57
  • @VinayVeluri FYI I downvoted your first answer before edit (that solution is different creation of spy). Your edit points to right direction, but unfortunately that answer was already posted by me. – luboskrnac Sep 25 '14 at 12:59
  • @lkrnac, even then, I have given reference to API even before my edit. I just took the copy of matter from that link and pasted here. What is so wrong with creation of spy with new object ? Still how can you mark them as same ? They are not same !! – Vinay Veluri Sep 25 '14 at 13:06
  • @lkrnac, if you dont get the functionality right with spying as OP asked, why to spy the object in that manner and use doThrow ? Why not create spy with new object ? How is that same ?? When you cannot simulate the functionality of that object, can you show me an example to show how does that work same ? – Vinay Veluri Sep 25 '14 at 13:09
  • @VinayVeluri Sorry don't get your comments at all. Your creation of spy (DeviceInfoHolderPopulator spyDeviceInfoHolderPopulator = spy(new DeviceInfoHolderPopulator());) is equivalent to creation if spy in question and have no impact on spy's behaviour – luboskrnac Sep 25 '14 at 13:15
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/61909/discussion-between-vinayveluri-and-lkrnac). – Vinay Veluri Sep 25 '14 at 13:32