2

Suppose, I have a test class with two methods as follows:

public class TestClass {        
   @Mock
   TestClass testObject;

   @Test
   public void method1() {
      doReturn("str").when(testObject).method2();

      String s1 = testObject.method2(); // This line gives compilation 
      //error. Type mismatch cannot convert from void to string
   }

   @Test
   public void method2() {
   }    

I am basically trying to mock method2 which is a dependency in method1.

But as you can see, the method2 return type is void. So, I am using doReturn to mock it.

As far as my understanding goes, although the method2 's return type is void, after I mock it, the mocked version of method2 should return String type.

But, as I have commented in method1, it is giving type mismatch.

hermit
  • 1,048
  • 1
  • 6
  • 16
  • @D.Peter doReturn/when is used to mock void methods. I am trying to do the same but have to idea what I am missing.. – hermit Jul 04 '17 at 10:04

2 Answers2

3

You are simply getting mocking wrong.

Mocking means: instead of create "real" objects of a specific class, you create a stub/dummy/mock that looks like an object of that class. But in reality - it is not.

Beyond that: mocking can not change the signature of a method. So your idea that you could somehow use mocking to have a void method return something is wrong.

You are simply going down the wrong rabbit hole - what you intend to is not possible.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • Thank you for your suggestion... I was basically trying to mock a method having a return type void. I was going through this link and it suggested that I could do that using doReturn/when : https://stackoverflow.com/questions/2276271/how-to-make-mock-to-void-methods-with-mockito So, I was trying to mock a method with void return type and expecting string as a return value . But seems you cannot do that. – hermit Jul 04 '17 at 11:48
  • In my actual service class, the method2 returns a value of type String. But, in my test class I changed the return type of method2 to void since it is a better coding practice. So, even after changing the return type of method2 to void, I want it to return a value of type String when I call it inside method1. I tried to achieve it as I have demonstrated in my question by the help of mocking. But, I was getting type mismatch error. So, what I am trying to achieve is not possible? – hermit Jul 04 '17 at 12:08
  • Exactly. And what you are describing there is **not at all** a *better* coding practice. Not sure where you got that idea. Beyond that: please dont get into the "more questions written up in comments" ping pong. – GhostCat Jul 04 '17 at 12:14
  • I meant, setting the return type of a test method to void is a better coding practice. – hermit Jul 04 '17 at 12:15
  • All I wanted was to have better understanding about the doReturn/when, which should supposedly help in mocking method with return type void. Your answer suggested it was not helpful but did not help me understand how I am using the doReturn/when wrong. Anyways I have upvoted your answer. – hermit Jul 04 '17 at 12:27
  • Sigh. A void method does **not** return a value. You can't use `doReturn()` to change the signature of a method. The signature of a method is a fixed property of the underlying class. It does not make sense to call doReturn() for a void method. If at all, you do something like `when(foo.voidMethod()).thenThrow()` for example. I am not sure how often I have to repeat that your whole idea is sorry, nonsense. It starts with the fact that you seem to miss the fact that you have A) production code and B) test code. You mock objects only for one reason: so you can pass them into some **production** – GhostCat Jul 04 '17 at 12:30
  • class object in order to make that object testable. There is absolutely no point in trying to change the signature. Again: it is not **better** practice to try that. I think you really have to step back and read some books / tutorials about testing and how to use mocking for unit testing. Because your comments imply that you have *no* understanding of what these terms mean. This is not meant to be rude - just my impression after reading your comments. – GhostCat Jul 04 '17 at 12:31
  • Thank you for your comments. I assumed mocking allows you to change the return type of the method. And this confusion came from this link which suggests that you can mock method with return type void with doReturn/when. https://stackoverflow.com/questions/2276271/how-to-make-mock-to-void-methods-with-mockito Can you help me in understanding how you can mock methods with return type void with doReturn/when... – hermit Jul 04 '17 at 12:39
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/148319/discussion-between-ghostcat-and-hermit). – GhostCat Jul 04 '17 at 12:41
0

I think you're using the wrong method. doReturn allows you to "inject" the result of the execution. If you want to "falsify" the whole method execution you should consider using doAnswer:

doAnswer(new Answer<Void>() {
    public Void answer(InvocationOnMock invocation) {
      // whatever you want to execute here...
      // Simply return null
      return null;
    }
}).when(testObject).method2();
Alberto S.
  • 7,409
  • 6
  • 27
  • 46
  • Thank you for your answer. In my actual service class, the method2 returns a value of type String. But, in my test class I changed the return type of method2 to void since it is a better coding practice. So, even after changing the return type of method2 to void, I want it to return a value of type String when I call it inside method1. I tried to achieve it as I have demonstrated in my question by the help of mocking. But, I was getting type mismatch error. So, what I am trying to achieve is not possible? – hermit Jul 04 '17 at 12:11
  • You just **can't** do that. You can't change the erasure of a method. That's something that comes with static typed languages like Java. So you didn't "change the return type of method2 to void". You just defined a new method. And even if you did that you can't define a new method whose signature just differs from another on the return type – Alberto S. Jul 04 '17 at 12:26
  • If you keep insisting in executing that method I suppose you could use reflection but I'm not sure what would happen then – Alberto S. Jul 04 '17 at 12:26
  • the method on the service class has return type String. And later when I wrote a test for that method in test class, I changed the return type to void. Thank you for your response, it seems I was doing things wrong. – hermit Jul 04 '17 at 12:31