How do I change the default return value for Strings in Mockito?

java, mocking, mockito, unit-testing

Solution

I was able to completely answer my own question.

In this example an address with the Locality of Louisville is generated while the other fields look like "address.getStreet1();".

private Address createAddress(){
    Address address = mock(Address.class, new StringAnswer() );

    when(address.getLocality()).thenReturn("Louisville");

    ISOCountry isoCountry = mock(ISOCountry.class);
    when(isoCountry.getIsocode()).thenReturn("US");
    when(address.getCountry()).thenReturn(isoCountry);

    return address;
}

private class StringAnswer implements Answer<Object> {
    @Override
    public Object answer(InvocationOnMock invocation) throws Throwable {
           if( invocation.getMethod().getReturnType().equals(String.class)){
               return invocation.toString();
           }
           else{
               return Mockito.RETURNS_DEFAULTS.answer(invocation);
           }
       }
}

Problem

This issue from 2010 hints at what I'm trying to do. I'm working on a unit test which exercises code that requires many mocked objects to do what it needs to do (testing HTML + PDF rendering). For this test to be successful I need many mocked objects to be generated and each of these objects ultimately return some String data to the code being tested. I think I can do this by implementing either my own `Answer` class or `IMockitoConfiguration`, but I am not sure how to implement those so they only affect methods which return Strings. I feel that the following code is close to what I want. It throws a cast exception, `java.lang.ClassCastException: java.lang.String cannot be cast to com.mypackage.ISOCountry`. I think this means I need to somehow default or limit the `Answer` to only affect the defaults for `String`. ``` private Address createAddress(){ Address address = mock(Address.class, new StringAnswer() ); /* I want to replace repetitive calls like this, with a default string. I just need these getters to return a String, not a specific string. when(address.getLocality()).thenReturn("Louisville"); when(address.getStreet1()).thenReturn("1234 Fake Street Ln."); when(address.getStreet2()).thenReturn("Suite 1337"); when(address.getRegion()).thenReturn("AK"); when(address.getPostal()).thenReturn("45069"); */ ISOCountry isoCountry = mock(ISOCountry.class); when(isoCountry.getIsocode()).thenReturn("US"); when(address.getCountry()).thenReturn(isoCountry); return address; } //EDIT: This method returns an arbitrary string private class StringAnswer implements Answer<Object> { @Override public Object answer(InvocationOnMock invocation) throws Throwable { String generatedString = "Generated String!"; if( invocation.getMethod().getReturnType().isInstance( generatedString )){ return generatedString; } else{ return Mockito.RETURNS_DEFAULTS.answer(invocation); } } } ``` How can I set up Mockito to return a generated String by default for methods on a mocked class which return String? I found a solution to this part of the question on SO For extra points, how can I make that generated value be a String which is in the form `Class.methodName`? For example `"Address.getStreet1()"` instead of just a random String?

Original source

Related problems