9

I tried to follow the example offered in the answer to this very similar question, but it does not work for me. I get the following error message:

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)

I need a simple mock instance of an enum class. I don't need to mock any of its methods.

Here is the class I want to mock:

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

I have the following TestNG setup:

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);
    }
}
Selena
  • 2,208
  • 8
  • 29
  • 49
  • Enum classes are final classes so you can't mock them. Perhaps create a higher level interface that your Enum can implement, and then mock that? – Dave Lugg May 08 '15 at 15:10
  • There are lots of links saying that PowerMock can do it: https://groups.google.com/forum/#!topic/powermock/hqrJaMi0Zrc, https://code.google.com/p/powermock/source/browse/trunk/modules/module-test/powermock/junit4-test/src/test/java/samples/junit4/enummocking/EnumMockingTest.java?r=759, – Selena May 08 '15 at 15:13
  • That second link looks like an example, is there something that doesn't work when you try it? – Dave Lugg May 08 '15 at 15:17
  • 1
    Why do you need to do this? I can't think of a situation where you would need to mock an enumeration. –  May 08 '15 at 15:20
  • @Toby, enum classes can have methods defined that you may want to seperate out from your class under test. – Dave Lugg May 08 '15 at 15:21
  • Which very similar question? In any case, **don't mock enums**: Java guarantees that the only possible enum values are listed in the `values()` array (and other similar guarantees), and a mock instance would invalidate that. Instead split out the functionality into an interface, have the enum implement the interface, and then mock the interface as much as you'd like. – Jeff Bowman May 08 '15 at 16:47
  • @Dave Lugg The second example is a Junit test which uses a construct that is not available in TestNG. My test is part of a larger TestNg test suite. – Selena May 08 '15 at 17:38
  • @Jeff Bowman My TestEnumerable class is an enum implementing an interface. I tried mocking IEnumerable> and it didn't work. – Selena May 08 '15 at 17:40
  • I hope this answer might help you. http://stackoverflow.com/questions/19949762/mockito-how-to-match-any-enum-parameter – Rocky Mena Nov 16 '15 at 12:05
  • @JeffBowman I have an enum that implements the Interface. I am trying to mock that interface, but my service class is still invoking the real implementation and not the mocked instance. How do I tell my service layer to use the mocked version? I am using initMocks(true) and InjectMocks. I tried `@Mock InterfaceName interfaceName; and also InterfaceName interfaceName = Mockito.mock(InterfaceName.class); – wheeleruniverse May 29 '18 at 18:17
  • @jDub9 That's definitely a separate question, and doesn't belong as a comment here. Please ask it separately, paste in as much code as it takes to reproduce the problem, and link to this question to indicate you've read it and still have an unsolved problem. – Jeff Bowman May 29 '18 at 18:19
  • It's fine I solved the problem messily. I put a method in my enum where I set some variable with the data I want returned then if it's set the service layer returns that instead of fetching the real data. I've already wasted too many hours struggling with this framework. – wheeleruniverse May 29 '18 at 18:35

3 Answers3

5

You need to run this with 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);
    }
}
steves165
  • 74
  • 2
  • 7
3

I got this working by extending the PowerMockTestCase class that handles this kind of thing for 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);

    }
}
Selena
  • 2,208
  • 8
  • 29
  • 49
1

Hi guys, to me worked as below:

First add power mockito on pom.xml:

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

and then on my class:

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