-1

I have a class that I am trying to unit test. This class extends another class that I am not interested in unit testing at this time.

The following code is an over simplification of the code I am trying to test.

package com.example.somePackage;
public class ApiBase {
  protected <T extends SomeClass> t getApi(Class<T> apiClass) {/* some logic*/}
}


package com.example.anotherPackage;
public MagicApiImpl extends ApiBase {
  private final MagicApiHandler apiHandler = new MagicApiHandler();

  public String doSomeStuff(String someString) {
    final BookApi bookApi = getApi(BookApi.class);
    // some logic
    return apiHandler.someMethod(bookApi, someString);
  }
}

I would like to test doSomeStuff() on MagicApiImpl The part I would like to mock is what comes back in getApi().

At first go I tried simply creating an Instance of MagicApiImpl and setting all the behind the scenes things that happen but that started to become over complex for the scenario I want to test and the number of times I need to test it in other classes. I will handle the testing of the logic in getApi() in a test of its own.

It would be helpful to use EasyMock to test this as it is what a majority of the tests for this project are written in but I would not be overly apposed to using mockito.

Edit

Okay I was reading about the Mockito.spy() That would have been wonderful but sadly getApi is protected and in another package. Worst case I could fall back on placing all the tests in that package but that makes it difficult track code.

buzzsawddog
  • 662
  • 11
  • 32
  • 5
    This is a strong case for favoring composition instead of inheritance, as being able to inject `getApi` would make this easier to test. – Makoto Dec 05 '17 at 17:19
  • @Makoto I agree. But.. That is not helpful at this time. In this project I am simply tasked with writing the test. We cant all save the world and rewrite things the way they should be. – buzzsawddog Dec 05 '17 at 17:37
  • I disagree. Making your code testable is part of testing. As it stands, mocking this will be *incredibly* difficult since it relies on a partial mock of the instance you're testing, and as for the `final` field...that's even worse. You are going to want to appeal to whomever tasked you with testing this to allow you to make it easier to test, which shouldn't be terribly difficult. – Makoto Dec 05 '17 at 17:38
  • Check my updated answer, it is supported in Easymock with partial mocking. – Rafael Guillen Dec 05 '17 at 18:10

1 Answers1

-1

Using Easymock partial mocks your test should look like this:

    @Test
    public void test() {
        MagicApiImpl impl = EasyMock.createMockBuilder(MagicApiImpl.class)
            .addMockedMethod("getApi")
            .createMock();
        EasyMock.expect(impl.getApi(BookApi.class)).andReturn(/**Wharever you need*/);
        EasyMock.replay(impl);
        String input = "INPUT";
        String output = impl.doSomeStuff(input);
        System.out.println("The OUTPUT is: " + output);
        EasyMock.verify(impl);
        //Run asserts here
    }

Reference: http://easymock.org/user-guide.html#mocking-partial

Rafael Guillen
  • 1,343
  • 10
  • 25