Re: PowerMock : can i mock enums?

11,857 views
Skip to first unread message

Jan Kronquist

unread,
Mar 2, 2009, 2:22:30 AM3/2/09
to powe...@googlegroups.com
Yes!

I'll just re-post Ulrik's example here. We will put this on the
website as well..

An enum will result in a corresponding final Java class, created by
the compiler. Mocking an enum means mocking a final class and possibly
also static methods. I'll show here an enum and two different tests.
Both tests will create a power mock as usual:

Planet planetMock = PowerMock.createMock(Planet.class);

The first test will mock the static method values (provided by the
compiler) to return only our planetMock. In order to do this, it also
needs to call mockStatic(Planet.class). The second test will go
further and change the static Planet.MARS field to be our planetMock.
Both tests will then shortcut the Planet logic and claim that the
surfaceWeight on our mock planet is always 50. It's a stupid test, but
it illustrates the point.

The complete source files are attached. Here are the dependencies I
needed (available in the with-dependencies download):
powermock-1.2-full.jareasymockclassextension-2.4.jareasymock-2.4.jar
junit-4.4.jarobjenesis-1.1.jarcglib-nodep-2.1_3.jarjavassist-3.9.0.GA.jarHere
is the (somewhat abbreviated) enum:

public enum Planet {
...
MARS (6.421e+23, 3.3972e6),
...
PLUTO (1.27e+22, 1.137e6);

private final double mass; // in kilograms
private final double radius; // in meters
Planet(double mass, double radius) {
this.mass = mass;
this.radius = radius;
}
public double mass() { return mass; }
public double radius() { return radius; }

// universal gravitational constant (m3 kg-1 s-2)
public static final double G = 6.67300E-11;

public double surfaceGravity() {
return G * mass / (radius * radius);
}
public double surfaceWeight(double otherMass) {
return otherMass * surfaceGravity();
}
}

Here are the tests:

@RunWith(PowerMockRunner.class)
@PrepareForTest(Planet.class)
public class TestMyEnum {
@Test
public void testEnum() throws Exception {
Planet planetMock = PowerMock.createMock(Planet.class);
mockStatic(Planet.class);

double earthWeight = 75D;
double mass = earthWeight / Planet.EARTH.surfaceGravity();

// let's mock Planet.values to return only our mock
expect(Planet.values()).andReturn(new Planet[] { planetMock });

// let's mock surfaceWeight to always return 50
expect(planetMock.surfaceWeight(mass)).andReturn(50D);

replay(Planet.class);
replay(planetMock);

for (Planet p : Planet.values()) {
double surfaceWeight = p.surfaceWeight(mass);
assertEquals(50D, surfaceWeight, 0.0D);
System.out.printf("Your weight on %s is %f%n", p, surfaceWeight);
}

verify(Planet.class);
verify(planetMock);
}

@Test
public void testSpecificEnum() throws Exception {
Planet planetMock = PowerMock.createMock(Planet.class);

double earthWeight = 75D;
double mass = earthWeight / Planet.EARTH.surfaceGravity();

// let's mock surfaceWeight to always return 50
expect(planetMock.surfaceWeight(mass)).andReturn(50D);

// let's mock MARS to be our mock instead
Whitebox.setInternalState(Planet.class, "MARS", planetMock);

replay(planetMock);

double surfaceWeight = Planet.MARS.surfaceWeight(mass);
assertEquals(50D, surfaceWeight, 0.0D);
System.out.printf("Your weight on %s is %f%n", Planet.MARS,
surfaceWeight);

verify(planetMock);
}
}

/Jan


> Hey,
>
> I cant find anything about it on main site, can i mock enums?
>
> Yours sincerely,
> Raveman
>

dfabulich

unread,
Mar 12, 2009, 4:04:26 PM3/12/09
to PowerMock
Thanks for the tip. Note that this does NOT work in PowerMock 1.2 if
the enum is a member type of another class, e.g.

class Astronomy {
enum Planet { ... }
}

In that case, you get the (misleading) error "Cannot subclass final
class Astronomy$Planet". It works fine if you refactor Planet from a
member type to a top level type. I had incorrectly believed that
PowerMock could not mock enums at all until I stumbled across this
thread. I've filed Issue 95 on this. http://code.google.com/p/powermock/issues/detail?id=95

On Mar 2, 12:22 am, Jan Kronquist <jan.kronqu...@gmail.com> wrote:
> Yes!
>
> I'll just re-post Ulrik's example here. We will put this on the
> website as well..
>
> Anenumwill result in a corresponding final Java class, created by
> the compiler. Mocking anenummeans mocking a final class and possibly
> also static methods. I'll show here anenumand two different tests.

Johan Haleby

unread,
Mar 13, 2009, 6:53:44 AM3/13/09
to powe...@googlegroups.com
Thanks for pointing this out. I'll give it a try asap and see if I can fix it.

Johan Haleby

unread,
Mar 13, 2009, 12:25:22 PM3/13/09
to powe...@googlegroups.com
I've verified this but the problem is not limited to enums though. That same problem occurs for all inner classes which are final. I looked briefly into a solution but I couldn't get it working, I suspect a bug in Javassist actually but it's too soon to tell for sure. Need to look more closely into this.
 
/Johan
 

Johan Haleby

unread,
Jul 28, 2012, 12:06:19 PM7/28/12
to powe...@googlegroups.com
I don't remember if the Mockito extension has support for mocking enums but I think it should be possible. What error message do you get?

On Fri, Jul 27, 2012 at 10:19 PM, Cameron Christiansen <c...@byu.edu> wrote:
You gave your example using easymock, would it be possible to provide a mockito example? I thought I had it all set up, but I'm getting an error that may or may not be related. The only changes I see really are PowerMock.createMock == PowerMockito.mock (and the typical convertion in syntax for "when" and the "and then").
--
You received this message because you are subscribed to the Google Groups "PowerMock" group.
To view this discussion on the web visit https://groups.google.com/d/msg/powermock/-/sL1oPjwrw2YJ.
To post to this group, send email to powe...@googlegroups.com.
To unsubscribe from this group, send email to powermock+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/powermock?hl=en.

Reply all
Reply to author
Forward
0 new messages