lundi 7 décembre 2015

mock constructor and super injected field with PowerMockito

I hope the example code snippets are enough to rebuild my problem.

I Have a class TreeWalker and a sub class ABCTreeWalker extends TreeWalker. I work with Spring Dependency Injection and in the TreeWalker I have a dependency Helper helper; which is protected and thus also available in the ABCTreeWalker. All dependencies like this helper are field-injected with Springs @Autowired, so there is no setter.

public class TreeWalker {

    @Autowired
    protected Helper helper;
}


public class ABCTreeWalker extends TreeWalker {

    @Override
    public void doSomething() {
        String something = helper.getSomething();
        InstanceModel instanceModel = new InstanceModel(something);
        // ... more stuff ...
    }
}

I need to create a Unit-Test for the ABCTreeWalker class in which I need to do two things:

  • Inject a mock of the helper into my ABCTreeWalker class under test
  • mock the constructor call

My Test runs with the @RunWith(PowerMockRunner.class) which allows to inject the helper with @InjectMocks and @Mock Annotations. BUT: In order to prepare for the constructor mock I need to prepare the Class under Test which is ABCTreeWalker with the annotation @PrepareForTest(ABCTreeWalker.class). And if I do this, the injection won't happen anymore (I guess because it came from the super class).

@RunWith(PowerMockRunner.class)
@PrepareForTest(ABCTreeWalker.class)
public class ABCTreeWalkerTest {

    @InjectMocks
    private ABCTreeWalker abcTreeWalker;

    @Mock
    private Helper helper;

    @Test
    public void testVisitGui() throws Exception {
        // ... more stuff ...
        when(helper.getSomething()).thenReturn("test");
        InstanceModel instanceModel = mock(InstanceModel.class);
        PowerMockito.whenNew(InstanceModel.class)
             .withArguments("test")
             .thenReturn(instanceModel);
        // ... more stuff ...

        abcTreeWalker.doSomething(); // execute

        // assertions etc.
 }

So what can I do now?

  • I could inject the helper in my ABCTreeWalker, but that is redundant
  • I probably could create a setter, but that would only for the test
  • I can't rmeove Powermock because of the constructor mocking

Do you guys have suggestions?

Aucun commentaire:

Enregistrer un commentaire