PowerMock extension to Mockito

90 views
Skip to first unread message

Johan Haleby

unread,
Nov 24, 2008, 5:57:18 AM11/24/08
to moc...@googlegroups.com
Hi,

Me and a colleague are developing an open source framework called PowerMock which is an extension to EasyMock that allows for mocking of static methods, constructors, final classes and methods, private methods, removal of static initializers and many other things that are normally not possible. We're thinking about implementing an extension to Mockito as well, the basic stuff shouldn't be too difficult for us to implement (mocking final classes and method actually works out of the box using PowerMock and Mockito today but you're stuck with EasyMock dependencies that are not really needed in this case). Does this sound interesting to you? If it does, are you interested in all features or just some (have a look at www.powermock.org for a list of features)? Of course it'll just will be an extension so we'll just supply a couple of more API methods and annotations on top of your API, i.e. some kind of "PowerMockito" extension just as classextension is an extension to EasyMock.

/Johan

Gili Tzabari

unread,
Nov 24, 2008, 10:21:23 AM11/24/08
to moc...@googlegroups.com

I would love to know how this works under the hood because there are
other frameworks, such as Google Guice, that could really benefit from
such techniques. With respect to Mockito, so long as you maintain the
existing API I think it would be a welcome addition (I'm not a Mockito
committer, just an end-user).

Gili

Johan Haleby wrote:
> Hi,
>
> Me and a colleague are developing an open source framework called
> PowerMock which is an extension to EasyMock that allows for mocking of
> static methods, constructors, final classes and methods, private
> methods, removal of static initializers and many other things that are
> normally not possible. We're thinking about implementing an extension to
> Mockito as well, the basic stuff shouldn't be too difficult for us to
> implement (mocking final classes and method actually works out of the
> box using PowerMock and Mockito today but you're stuck with EasyMock
> dependencies that are not really needed in this case). Does this sound
> interesting to you? If it does, are you interested in all features or
> just some (have a look at www.powermock.org <http://www.powermock.org>

Johan Haleby

unread,
Nov 25, 2008, 2:19:25 AM11/25/08
to moc...@googlegroups.com
PowerMock uses byte-code manipulation to allow for testability. What is
that Guice needs to do that can't be done now?

We will of course try to stay as close to the original Mockito API as
possible.

/Johan

Gili Tzabari

unread,
Nov 25, 2008, 2:42:48 AM11/25/08
to moc...@googlegroups.com

Guice and some of its plugins (such as warp-persist) use AOP-style
instrumentation which doesn't work against private or final methods. For
example, I use:

@Transactional(rollbackOn=Exception.class)
public void someMethod()
{}

but if the method is private or final it will silently ignore the
annotation and will be hard to troubleshoot the problem. Ideally we
should be able to operate on private/final methods.

Gili
> <http://www.powermock.org> <http://www.powermock.org>

Johan Haleby

unread,
Nov 25, 2008, 2:58:11 AM11/25/08
to moc...@googlegroups.com
Ah I see, I've never run into any problems myself using guice-warp but I can see that this is definitely a problem. It's actually the same problem as with creating mock objects for final classes or methods, you (well CGLib) cannot create a proxy around these objects since they cannot be extended. We solve this by modifying the byte-code and intercepting all calls and guice-warp could probably do the same. But they would probably not want to go with the approach that we've taking in PowerMock. PowerMock uses a custom classloader that loads and deals with classes that needs to be modified, this way we don't have to start an agent and thus we don't need to modify the IDE or build-environment. I guess guice-warp would be better off using an agent to do the byte-code instrumentation (just as aspectj).

/Johan

Gili Tzabari

unread,
Nov 25, 2008, 3:07:34 AM11/25/08
to moc...@googlegroups.com

Are you saying you modify the original class the first time it is
loaded (as opposed to extending it with some proxy)? Makes me wonder why
everyone doesn't do this instead of extending the class. I totally hate
having to provide a no-op constructor and public methods (it kills good
design)!

Guice already uses a custom class-loader and using CGLIB has been shown
to break backwards compatibility with the unproxied code so this might
interest them.

Gili
> > <mailto:gili.t...@gmail.com <mailto:gili.t...@gmail.com>>>

Johan Haleby

unread,
Nov 25, 2008, 3:18:54 AM11/25/08
to moc...@googlegroups.com
Yes this is basically what we do, all method calls (and field access calls, new invocation calls etc) are routed to our MockGateway which then either just delegates the call to the original object or we invoke an EasyMock InvocationHandler just as the CgLib proxy would do normally. This way we don't have to use inheritance. We do a lot of other stuff as well, but essentially having the MockGateway is a good way of deciding what should happen to certain calls. I think most projects use CgLib because it's easy and well known.

With PowerMock we don't enforce you to use a certain design for the sake of testability. There are of course many other reasons for why you'd still like to have good design but now you don't have to concern yourself with the testability issues (mostly).

/Johan

Gili

unread,
Nov 25, 2008, 11:58:09 AM11/25/08
to mockito
Johan,

I brought up your approach on the Guice mailing list:
http://groups.google.com/group/google-guice/browse_thread/thread/898215a4e4d7b545

Gili

On Nov 25, 3:18 am, "Johan Haleby" <johan.hal...@gmail.com> wrote:
> Yes this is basically what we do, all method calls (and field access calls,
> new invocation calls etc) are routed to our MockGateway which then either
> just delegates the call to the original object or we invoke an EasyMock
> InvocationHandler just as the CgLib proxy would do normally. This way we
> don't have to use inheritance. We do a lot of other stuff as well, but
> essentially having the MockGateway is a good way of deciding what should
> happen to certain calls. I think most projects use CgLib because it's easy
> and well known.
>
> With PowerMock we don't enforce you to use a certain design for the sake of
> testability. There are of course many other reasons for why you'd still like
> to have good design but now you don't have to concern yourself with the
> testability issues (mostly).
>
> /Johan
>
> > > On Tue, Nov 25, 2008 at 8:42 AM, Gili Tzabari <gili.tzab...@gmail.com
> > > <mailto:gili.tzab...@gmail.com>> wrote:
>
> > >            Guice and some of its plugins (such as warp-persist) use
> > >     AOP-style
> > >     instrumentation which doesn't work against private or final methods.
> > For
> > >     example, I use:
>
> > >     @Transactional(rollbackOn=Exception.class)
> > >     public void someMethod()
> > >     {}
>
> > >            but if the method is private or final it will silently ignore
> > the
> > >     annotation and will be hard to troubleshoot the problem. Ideally we
> > >     should be able to operate on private/final methods.
>
> > >     Gili
>
> > >     Johan Haleby wrote:
> > >      > PowerMock uses byte-code manipulation to allow for testability.
> > >     What is
> > >      > that Guice needs to do that can't be done now?
>
> > >      > We will of course try to stay as close to the original Mockito API
> > as
> > >      > possible.
>
> > >      > /Johan
>
> > >      > On Mon, Nov 24, 2008 at 4:21 PM, Gili Tzabari
> > >     <gili.tzab...@gmail.com <mailto:gili.tzab...@gmail.com>
> > >      > <mailto:gili.tzab...@gmail.com <mailto:gili.tzab...@gmail.com>>>

Gili

unread,
Nov 25, 2008, 11:58:56 AM11/25/08
to mockito
Sorry, wrong URL. Please see http://groups.google.com/group/google-guice/browse_thread/thread/96162e9e9806852
instead.

Gili

On Nov 25, 11:58 am, Gili <gili.tzab...@gmail.com> wrote:
> Johan,
>
> I brought up your approach on the Guice mailing list:http://groups.google.com/group/google-guice/browse_thread/thread/8982...

szczepiq

unread,
Nov 26, 2008, 8:57:43 AM11/26/08
to moc...@googlegroups.com
Hi Johan,

Sorry it took me quite a while to respond. I've been looking at
Powermock from sometime and there are couple of really smart ideas.
Surely it's way nicer than other "mock the unmockable" libraries.

About the powermockito extension. My school of kung-fu is tdd. My code
is easily testable from scratch. Powermock hacks the bytecode and does
reflection magic to squeeze out some testability from the code.

>With PowerMock we don't enforce you to use a certain design for the sake of testability.

Yes, and this is exactly my problem with PowerMock... I like when
tests enforce good design, for example, by promoting object
orientation over procedural static methods, etc. That's why I'm
sticking to dependency-injection mocking frameworks like mockito,
easymock, jmock and I'm not that interested in powermockito extension.
But I'm sure there are users with totally different opinion, as usual
:)

Thanks for letting us know about powermock. I still don't like the way
mockito silently ignores final methods so I will probably look at
PowerMock to find some inspiration / or ask you guys

Cheers!
Szczepan Faber

Johan Haleby

unread,
Nov 26, 2008, 10:02:29 AM11/26/08
to moc...@googlegroups.com
I agree with most of what you're saying, never would we encourage anyone to write sloppy code just because it's now possible to test it. But even if you stick with "good design" and tdd yourself you may be forced to integrate with other frameworks, standard API:s or some other legacy code where you'd like to mock static methods, remove static initializers etc. And sometimes final methods and doing "new" in your own code are justifiable as well and perhaps you'd like to mock them in a unit test. And also I find it useful to be able to read private state without needing to add a getter for this state if it's not needed in the production code. So I don't agree that it's a problem with PowerMock, it's actually a problem that PowerMock tries to address :). You should use PowerMock when you have the need, you should not misuse it! And it is for these reasons I think it would be nice with a similar extension to Mockito as well, it simply gives the users more choice, but they can decide for themselves whether to use it or not.

/Johan

Gili Tzabari

unread,
Nov 26, 2008, 11:43:00 AM11/26/08
to moc...@googlegroups.com
szczepiq wrote:
> Yes, and this is exactly my problem with PowerMock... I like when
> tests enforce good design, for example, by promoting object
> orientation over procedural static methods, etc.

Promoting is one thing. Forcing is another. You "promote" by inside
your own library space by designing good APIs. The key is not to force
that opinion on the end-user. Hibernate is an example of what *not* to
do. It is impossible to use Hibernate without modifying your design. In
fact, you're virtually assured that your API will contain multiple
anti-patterns if you use that framework.

My 2 cents: try designing Mockito as a library, not a framework.

Gili

Johan Haleby

unread,
Nov 26, 2008, 12:04:02 PM11/26/08
to moc...@googlegroups.com
I've made a really simple demonstration on how to mock final methods using PowerMock and Mockito. You can see the how the test looks like here:
http://code.google.com/p/powermock/source/browse/trunk/modules/module-test/powermockito/junit4/src/test/java/org/powermock/modules/powermockito/test/junit4/finalmocking/FinalDemoTest.java

Dan North

unread,
Nov 26, 2008, 4:53:18 PM11/26/08
to moc...@googlegroups.com
Hi Gill.

2008/11/26 Gili Tzabari <gili.t...@gmail.com>

Sorry, I'm not getting what you mean here. Mockito is a library. It's not even a runtime library, it's a development support library (unless you ship it with your application). It's about as unobtrusive as a library could be. It's there if you want it and invisible if you don't.

I also don't get the comparison with Hibernate (while I completely agree with your assessment :). Hibernate is an intrusive framework that muddles object-relational mapping in with your domain model, making it hard to do either right. Mockito is a mocking framework to support outside-in test-driven development, which if anything encourages good design by highlighting unnecessary coupling (inasmuch as if it's difficult to mock it's probably not very well factored).

Most realistic applications interact with many third-party libraries or frameworks, many of which expose poor APIs (requiring you to couple to concrete classes rather than interfaces, arbitrarily making methods final so you can't override them for testing, etc.). A naive design can allow this poor design to leak into your own domain model and pollute it.

Mockito leads you down the path of insulating yourself from these classes by putting in your own adapter layer behind an interface, which gives you the opportunity to give the interface a meaningful name. (In domain-driven design terms this adapter-plus-interface is called an "anti-corruption layer").

Mockito is opinionated but it isn't dogmatic. I believe a good solution to integrating with a crufty API is to protect yourself from it rather than building power tools that allow it to pollute your own domain model.

I'll get off my soapbox now.

Gili

Cheers,
Dan

Gili Tzabari

unread,
Nov 26, 2008, 5:03:04 PM11/26/08
to moc...@googlegroups.com

Ironically, I don't disagree with the design you are advocating. I
guess what I am trying to say is "everything in moderation" (Hibernate
being a clear violation we both agree on). If there are decent use-cases
for testing code that uses final methods (I can't think of any off the
top of my head) then Mockito shouldn't get in the way. That being said,
let's list those good use-cases first ;)

Gili

Dan North wrote:
> Hi Gill.
>
> 2008/11/26 Gili Tzabari <gili.t...@gmail.com
> <mailto:gili.t...@gmail.com>>

Jan Kronquist

unread,
Nov 27, 2008, 3:13:16 AM11/27/08
to mockito
Using an anti-corruption-layer is most often a good thing. I think
there are a few cases where it might not be or perhaps cases where you
want to be able to test your anti-corruption-layer. For instance, the
Java ME API contains lots of static method calls. To minimize your
code there might be reasons not to use an anti-corruption-layer or
perhaps test your low level byte-fiddling API calls actually works.
This is a good usecase for PowerMock.

Another usecase is for legacy code. I have often seen untestable
legacy code that the organization is too afraid to modify. Using
PowerMock you can actually start writing testcases without modifying
the code and start building your confidence.

As Johan writes, PowerMock is not intended as a general purpose mock
framework. It is intended for the tricky cases where you are not able
to write unit tests simply for technical limitations. We want to
support different mock framework API's so people can still be able to
use their favorite mock framework and get around those limitations.

Mockito is opinionated, PowerMock is not. So using PowerMock you can
write crappy code and still be able to test. This is obviously not our
aim! Don't run with scissors! Don't write crappy code with
PowerMock! :-)

/Jan

On 26 Nov, 22:53, "Dan North" <tasta...@gmail.com> wrote:
> Hi Gill.
>
> 2008/11/26 Gili Tzabari <gili.tzab...@gmail.com>

szczepiq

unread,
Nov 27, 2008, 6:30:32 PM11/27/08
to moc...@googlegroups.com
>Mockito is opinionated, PowerMock is not.

Oh, of course it is, like most .open source It's just opinionated differently :)

I hear you PowerMockers and what you say makes sense but still my
preference is "anti-corruption layer" + DI. I'm with Dan about
everything he said. Maybe I just never coded in Java ME (do you have
large user base in Java ME?), nor dealt with hardcore legacy code.
Anyway, mocking in legacy code is not very useful - I'd rather try to
write functional tests so that I can refactor aggressively. You say to
powermock tricky cases. If I introduce a new library to solve a tricky
case how would I know it's going to be used only for tricky cases?

Let's cut to the point. I'm not interested in power features so I'm
not the best person to be asked what should be in the extension. If
you find a real life example that demonstrates the strength of power
features I'd be mostly interested. I'm sure you will find users for
powermockito - hopefully not developers from my team :)

About final methods I mentioned earlier. Thanks for the example
mockito+powermock. The problem with final methods in Mockito is that
they might lead to confusing framework behavior. Usually the user
doesn't even know he's mocking a final method. For example see the
latest bug http://code.google.com/p/mockito/issues/detail?id=36 .
Fortunately I have an idea how to fix it unobtrusively.

Cheers,
Szczepan Faber

Cheers,
Szczepan Faber
Reply all
Reply to author
Forward
0 new messages