Search code examples
jmockit

How do I mock an inherited method that has generics with JMockit


I have this abstract class:

public abstract class Accessor<T extends Id, U extends Value>
{
   public U find(T id)
   {
        // let's say
        return getHelper().find(id);
   }
}

And an implementation:

public FooAccessor extends Accessor<FooId,Foo>
{
    public Helper getHelper
    {
        // ...
        return helper;
    }
}

And I would like to mock the calls to FooAccessor.find. This:

@MockClass(realClass=FooAccessor.class)
static class MockedFooAccessor
{
    public Foo find (FooId id)
    {
        return new Foo("mocked!");
    }
}

will fail with this error:

java.lang.IllegalArgumentException: Matching real methods not found for the following mocks of MockedFooAccessor:
Foo find (FooId)

and I understand why... but I don't see how else I could do it.

Note: yes, I could mock the getHelper method, and get what I want; but this is more a question to learn about JMockit and this particular case.


Solution

  • The only way around this I have found is to use fields

    @Test
    public void testMyFooMethodThatCallsFooFind(){
    MyChildFooClass childFooClass = new ChildFooClass();
    String expectedFooValue = "FakeFooValue";
    new NonStrictExpectations(){{
     setField(childFooClass, "fieldYouStoreYourFindResultIn", expectedFooValue);
    }};
    
    childFooClass.doSomethingThatCallsFind();
    
    // if your method is protected or private you use Deencapsulation class 
    // instead of calling it directly like above
    Deencapsulation.invoke(childFooClass, "nameOfFindMethod", argsIfNeededForFind);
    // then to get it back out since you used a field you use Deencapsulation again to pull out the field
    String actualFoo = Deencapsulation.getField(childFooClass, "nameOfFieldToRunAssertionsAgainst");
    
    assertEquals(expectedFooValue ,actualFoo);
    
    }
    

    childFooClass doesn't need to be mocked nor do you need to mock the parent.

    Without more knowledge of your specific case this strategy has been the best way for me to leverage jMockit Deencapsulation makes so many things possilbe to test without sacrificing visibility. I know this doesn't answer the direct question but I felt you should get something out of it. Feel free to downvote and chastise me community.