фиктивный конструктор и супервведенное поле с PowerMockito

Я надеюсь, что примеров фрагментов кода достаточно, чтобы перестроить мою проблему.

У меня есть класс TreeWalker и подкласс ABCTreeWalker extends TreeWalker. Я работаю с Spring Dependency Injection, и в TreeWalker у меня есть зависимость Helper helper;, которая защищена и, следовательно, также доступна в ABCTreeWalker. Все зависимости, подобные этой helper, вводятся полем с помощью Springs @Autowired, поэтому сеттера нет.

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 ...
    }
}

Мне нужно создать Unit-Test для класса ABCTreeWalker, в котором мне нужно сделать две вещи:

  • Внедрить макет helper в мой тестируемый класс ABCTreeWalker
  • издеваться над вызовом конструктора

Мой тест выполняется с @RunWith(PowerMockRunner.class), что позволяет вводить helper с аннотациями @InjectMocks и @Mock. НО: чтобы подготовиться к макету конструктора, мне нужно подготовить тестируемый класс, который равен ABCTreeWalker с аннотацией @PrepareForTest(ABCTreeWalker.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.
 }

Итак, что я могу сделать сейчас?

  • Я мог бы ввести helper в свой ABCTreeWalker, но это лишнее.
  • Я, наверное, мог бы создать сеттер, но это было бы только для теста
  • Я не могу удалить Powermock из-за насмешливого конструктора

У вас есть предложения?


person BAERUS    schedule 07.12.2015    source источник
comment
что вы получаете без @PrepareForTest(ABCTreeWalker.class)   -  person Guna    schedule 07.12.2015
comment
Тогда инъекция работает, но я больше не могу издеваться над вызовом конструктора.   -  person BAERUS    schedule 07.12.2015


Ответы (1)


Думали ли вы о конструкторе @Autowired

public class TreeWalker {
protected Helper helper;

@Autowired
public TreeWalker(Helper helper){
    this.helper = helper;
}

} А потом вызывать super() в конструкторе дочернего элемента?

person Iker Obregon Reigosa    schedule 07.12.2015
comment
Я могу изменить только дочерний класс, суперкласс исходит из зависимости от maven. Я работаю над кастомным решением стандартного продукта, где я не могу изменить последний. - person BAERUS; 11.12.2015
comment
Извините, я указал не тот класс. Конструктор может быть для класса ABCTreeWalker. public class ABCTreeWalker { @Autowired public ABCTreeWalker (Helper helper){ this.helper = helper; } - person Iker Obregon Reigosa; 11.12.2015