13

I have a void method "functionVoid" that informs a parameter.

public class MyMotherClass {
 @Inject
 MyClass2 myClass2

 public String motherFunction(){
  ....
  String test = "";
  myClass2.functionVoid(test);

  if (test.equals("")) {
      IllegalArgumentException ile = new IllegalArgumentException(
      "Argument is not valid");
      logger.throwing(ile);
      throw ile;
  }
  ....
 }
}

public class MyClass2 {

public void functionVoid(String output_value)
{ ....
 output_value = "test";

 ....
 }
}

How do I mock this method in the JUnit method my method "motherFunction"? In my example, the "test" variable is still empty.

@RunWith(MockitoJUnitRunner.class)
public class MyMotherClassTest {

 @Mock
 private MyClass2 myClass2 ;

 @InjectMock
 private final MyMotherClass myMotherClass = new MyMotherClass ();

 @Test
 public void test(){

  myMotherClass.motherFunction();     

 }
}
bric3
  • 40,072
  • 9
  • 91
  • 111
guliemo
  • 131
  • 1
  • 1
  • 3

4 Answers4

20

If you want to mock the return result of motherFunction then you need not worry about the internal implementation of the method (which ends up calling functionVoid). What you do need to do is provide Mockito with an instruction as to what to do when the method, motherFunction is invoked, this can be achieved via the when clause with syntax;

    when(mockedObject.motherFunction()).thenReturn("Any old string");

If that misses the point of what you are attempting to achieve then look at how to mock void methods in the documentation and determine whether the use of doAnswer is applicable here, something like;

doAnswer(new Answer<Void>() {

  @Override
  public Void answer(InvocationOnMock invocation) throws Throwable {
    String output_value = invocation.getArguments()[0];
    output_value = "Not blank";
    return null;
  }
}).when(myClass2).functionVoid(anyString());
Community
  • 1
  • 1
BrantApps
  • 6,362
  • 2
  • 27
  • 60
  • 1
    I want to mock : myClass2.functionVoid(test); – guliemo Jan 29 '13 at 13:11
  • Yep, so you use ````doAnswer````. You replace the implementation of ````functionVoid```` and can capture and modify the arguments and implementation according to what you want it to do. In the example above I changed output_value to "Not blank". You can also mock exceptions being thrown with ````doThrow````... - which is that you want to do? – BrantApps Jan 29 '13 at 13:29
  • 2
    This is the proper way to mock a void method, but isn't going to result in the `test` var changing after the call to 'functionVoid' though, as the sample above seems to expect. – Tom Tresansky Jan 30 '13 at 20:47
8

If you can change functionVoid() to accept a mutable object as the parameter, then you should be able to achieve what you want.

For example, if you change functionVoid() as follows:

public void functionVoid(StringBuilder output_value)
{ ....
 output_value.append("test");

 ....
 }

and invoke it in your motherFunction as follows:

public String motherFunction(){
  ....
  StringBuilder test = new StringBuilder();
  myClass2.functionVoid(test);

  if (test.toString().equals("")) {

Now modifying OceanLife's answer above, you should be able to do the following:

doAnswer(new Answer<Void>() {

  @Override
  public Void answer(InvocationOnMock invocation) throws Throwable {
    StringBuilder output_value = invocation.getArguments()[0];
    output_value.append("Not blank");
    return null;
  }
}).when(myClass2).functionVoid(any(StringBuilder.class)); 

Of course, if you can change functionVoid(), you could also just make it return a String instead of void.

mrjmh
  • 978
  • 10
  • 12
5

In my example, the "test" variable is still empty.

This is not a Mockito problem.

Take a look at this question and especially this answer.

The gist of it is that Java is pass by value (this is explained far better at the links above). Nothing in Mockito or Java will ever be able to make the test var anything other than an empty String. It's an empty String before the method call, and will be an empty String after the call.

You can change an object's state within a method (e.g. adding objects to a collection within a method) and see those changes when you exit the method, but you cannot change what object a var references within a method and expect those changes to "stick" once you exit the method. Strings however, are effectively immutable (no state to change), so you can't even do this.

Thus no modifications to test can be made within that method call.

Community
  • 1
  • 1
Tom Tresansky
  • 19,364
  • 17
  • 93
  • 129
0

If you want to check method someMethod(String arg) of object Obj then:

String argument = "";
Mockito.verify(Obj, Mockito.times(1)).someMethod(argument);

Obj has to be Mock or Spy. This works when you want to check if proper argument was passed to void method.

If your method modifies somehow argument then you should use assertion: someMethod(StringWrapper wrapper) that changes string.

// given
String argument = "a";
String expected = "a_changed";
String wrapped = new StringWrapper(a);

// when
someMethod(wrapped);

// then
Assert.assertEquals(wrapped.getString(), expected)

I am not sure if this what you were looking for?

Kostek
  • 147
  • 13