Powermock: как смоделировать метод в константе перечисления - PullRequest
0 голосов
/ 13 ноября 2018

У меня есть тип перечисления, который я использовал как набор фабрик для других объектов, которые реализуют общий интерфейс. упрощенная версия кода:

interface Operation { 
    void execute();
}

enum Factory {
    TYPE1(Class1::new),
    TYPE2(Class2::new);

    private Supplier<Operation> constructor;

    Factory(Supplier<Operation> constructor) {
        this.constructor = constructor;
    }

    Operation build() {
        return constructor.get(); 
    }
}

A упрощенная версия клиентского кода выглядит так:

class Client {
    private void run(EnumSet<Factory> required) {
        for (Factory x : required) {
            x.build().execute(); 
        }
    }

    // Some code that calls run() with the right EnumSet
}

Похоже, все это работает, как и ожидалось, поэтому я хочу написать несколько юнит-тестов.

Тестировать Factory легко, но Client оказывается сложнее. Проблема в том, что я не хочу начинать звонить на Operation (они много работают). Вместо этого я бы хотел, чтобы x.build() вернул фиктивный объект.

Я пытался использовать PowerMocks whenNew, чтобы перехватить создание объектов Operation, но это не работает (у меня фактически нет никаких «новых» операций). Я также пытался использовать Powermock «шпион», но это не удалось, потому что константы перечисления являются реальными объектами.

Есть идеи?

1 Ответ

0 голосов
/ 14 ноября 2018

Два решения:

  • вы настаиваете на использовании PowerMock (ito). Тогда простой вопрос: вы, вероятно, готовите не тот класс для тестирования. Вы должны умерить эти enum константы , и они являются внутренними классами. Но это возможно, см., Например, ответ .
  • вы отступаете и улучшаете свой производственный код, чтобы облегчить тестирование.

Например, вот так:

interface OperationProvider { 
    Operation build();
}

будет использоваться как:

enum Factory implements OperationProvider {

И теперь вы можете изменить свой клиентский код на

OperationProvider ourProvider = ...
whatever.build();...

Дело в том, что при использовании внедрения зависимостей вы просто передаете mocked OperationProvider. Это означает, что вы можете обойтись без необходимости полностью насмехаться над своим перечислением. Вам просто нужно убедиться, что в вашем производственном коде вы, очевидно, передаете одну из констант enum при инициализации, например, поля ourProvider.

...