Как я могу издеваться над экземпляром класса enum с помощью PowerMock & Mockito?

Я пытался следовать примеру, предложенному в ответе на этот очень похожий вопрос, но у меня это не работает. Я получаю следующее сообщение об ошибке:

java.lang.IllegalArgumentException: Cannot subclass final class class com.myproject.test.support.ExampleEnumerable
    at org.mockito.cglib.proxy.Enhancer.generateClass(Enhancer.java:447)
    at org.mockito.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
    at org.mockito.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:217)
    at org.mockito.cglib.proxy.Enhancer.createHelper(Enhancer.java:378)
    at org.mockito.cglib.proxy.Enhancer.createClass(Enhancer.java:318)
    at org.powermock.api.mockito.repackaged.ClassImposterizer.createProxyClass(ClassImposterizer.java:123)
    at org.powermock.api.mockito.repackaged.ClassImposterizer.imposterise(ClassImposterizer.java:57)
    at org.powermock.api.mockito.internal.mockcreation.MockCreator.createMethodInvocationControl(MockCreator.java:110)
    at org.powermock.api.mockito.internal.mockcreation.MockCreator.mock(MockCreator.java:58)
    at org.powermock.api.mockito.PowerMockito.mock(PowerMockito.java:143)

Мне нужен простой фиктивный экземпляр enum class. Мне не нужно издеваться над любым из его методов.

Вот класс, который я хочу издеваться:

public enum ExampleEnumerable implements IEnumerable<ExampleEnumerable> {
    EXAMPLE_ENUM_1("Test Enum 1"),
    EXAMPLE_ENUM_2("Test Enum 2");

    final String alias;

    ExampleEnumerable(final String alias) {
        this.alias = alias;
    }

    @SuppressWarnings({"VariableArgumentMethod", "unchecked"})
    @Override
    public @Nullable
    String getAlias(final @Nonnull IEnumerable<? extends Enum<?>>... context) {
        return alias;
    }
}

У меня есть следующая настройка TestNG:

import static org.powermock.api.mockito.PowerMockito.mock;

@PrepareForTest({ ExampleEnumerable.class})
@Test(groups = {"LoadableBuilderTestGroup"})
public class LoadableBuilderTest {

    private ExampleEnumerable mockEnumerable;

    @BeforeMethod
    public void setUp() {
        mockEnumerable = mock(ExampleEnumerable.class);
    }
}

person Selena    schedule 08.05.2015    source источник
comment
Классы Enum являются конечными классами, поэтому вы не можете над ними издеваться. Возможно, создайте интерфейс более высокого уровня, который может реализовать ваш Enum, а затем смоделируйте его?   -  person Dave Lugg    schedule 08.05.2015
comment
Есть много ссылок, говорящих о том, что PowerMock может это сделать: groups.google.com/ форум/#!topic/powermock/hqrJaMi0Zrc, code.google.com/p/powermock/source/browse/trunk/modules/ ,   -  person Selena    schedule 08.05.2015
comment
Эта вторая ссылка выглядит как пример, есть ли что-то, что не работает, когда вы пытаетесь это сделать?   -  person Dave Lugg    schedule 08.05.2015
comment
Зачем вам это нужно? Я не могу придумать ситуацию, когда вам нужно было бы издеваться над перечислением.   -  person    schedule 08.05.2015
comment
@Toby, в классах enum могут быть определены методы, которые вы, возможно, захотите отделить от тестируемого класса.   -  person Dave Lugg    schedule 08.05.2015
comment
Какой очень похожий вопрос? В любом случае не имитируйте перечисления: Java гарантирует, что только возможные значения перечисления перечислены в массиве values() (и другие подобные гарантии), и фиктивный экземпляр сделает это недействительным. Вместо этого разделите функциональность на интерфейс, сделайте так, чтобы перечисление реализовало интерфейс, а затем издевались над интерфейсом столько, сколько хотите.   -  person Jeff Bowman    schedule 08.05.2015
comment
@Dave Lugg Второй пример — это тест Junit, в котором используется конструкция, недоступная в TestNG. Мой тест является частью более крупного набора тестов TestNg.   -  person Selena    schedule 08.05.2015
comment
@Jeff Bowman Мой класс TestEnumerable — это перечисление, реализующее интерфейс. Я пытался издеваться над IEnumerable‹?›, и это не сработало.   -  person Selena    schedule 08.05.2015
comment
Я надеюсь, что этот ответ может помочь вам. stackoverflow.com/questions/19949762 /   -  person Rocky Mena    schedule 16.11.2015
comment
@JeffBowman У меня есть перечисление, которое реализует интерфейс. Я пытаюсь издеваться над этим интерфейсом, но мой класс обслуживания по-прежнему вызывает реальную реализацию, а не издевательский экземпляр. Как мне сообщить моему сервисному уровню, что нужно использовать фиктивную версию? Я использую initMocks(true) и InjectMocks. Я попробовал `@Mock InterfaceName interfaceName; а также InterfaceName interfaceName = Mockito.mock(InterfaceName.class);   -  person jDub9    schedule 29.05.2018
comment
@jDub9 jDub9 Это определенно отдельный вопрос, и здесь ему не место комментировать. Пожалуйста, задайте его отдельно, вставьте столько кода, сколько потребуется для воспроизведения проблемы, и дайте ссылку на этот вопрос, чтобы показать, что вы его прочитали и у вас все еще есть нерешенная проблема.   -  person Jeff Bowman    schedule 29.05.2018
comment
Это нормально, я решил проблему беспорядочно. Я помещаю метод в свое перечисление, где я устанавливаю некоторую переменную с данными, которые я хочу вернуть, а затем, если он установлен, уровень службы возвращает это вместо извлечения реальных данных. Я уже потратил слишком много часов на борьбу с этой структурой.   -  person jDub9    schedule 29.05.2018


Ответы (3)


Вам нужно запустить это с помощью PowerMockRunner

eg.

@RunWith(PowerMockRunner.class)
@PrepareForTest({ ExampleEnumerable.class})
@Test(groups = {"LoadableBuilderTestGroup"})
public class LoadableBuilderTest {
    private ExampleEnumerable mockEnumerable;

    @BeforeMethod
    public void setUp() {
        mockEnumerable = mock(ExampleEnumerable.class);
    }
}
person steves165    schedule 08.05.2015
comment
RunWith — это конструкция junit, и я использую TestNG, у которого нет этой конструкции. - person Selena; 08.05.2015
comment
Mockito не может издеваться/шпионить, потому что: - последний класс - person Yar; 19.07.2018

Я получил это, расширив класс PowerMockTestCase, который обрабатывает такие вещи для TestNG:

@PrepareForTest(TestEnumerable.class)
@Test(groups = {"LoadableBuilderTestGroup"})
public class LoadableBuilderTest extends PowerMockTestCase {

 private TestEnumerable mockEnumerable;

 @SuppressWarnings("unchecked")
    @BeforeMethod
    public void setUp() {
        mockEnumerable = PowerMockito.mock(TestEnumerable.class);

    }
}
person Selena    schedule 12.05.2015

Привет, ребята, у меня получилось так:

Сначала добавьте power mockito в pom.xml:

<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-junit4</artifactId>
    <version>2.0.4</version>
    <scope>test</scope>
</dependency>

а затем в моем классе:

@RunWith(PowerMockRunner.class)
@PrepareForTest({EnumClass.class})
public class EnumClassTest{
    private EnumClassTest enumClassTest;
    
    @Before
    public void setUp() {
        enumClassTest = mock(EnumClassTest.class);
    }
    
    @Test
    public void someMethod() {
        //My code test here
    }  
person Michael froids    schedule 11.11.2020