Mocking static Java methods

3,066 views
Skip to first unread message

New Groovy

unread,
Jul 16, 2013, 9:27:02 AM7/16/13
to spockfr...@googlegroups.com
Will global mocks mock/stub Java static methods that are called from Java classes under test?

I read this here: http://city81.blogspot.com/2013/04/mocking-static-methods-in-groovy.html

"The problem with mocking Java static methods though, when using Groovy for testing, is when they are called from Java classes and these calling classes are the ones you are trying to test. "

Thanks!

Peter Niederwieser

unread,
Jul 16, 2013, 2:13:04 PM7/16/13
to spockfr...@googlegroups.com
As stated in the docs (http://docs.spockframework.org), global mocks can only be used for code under test written in Groovy. If you need the same for Java, you'll have to use a mocking framework such as PowerMock or JMockit.

Cheers,
Peter

--
You received this message because you are subscribed to the Google Groups "Spock Framework - User" group.
To unsubscribe from this group and stop receiving emails from it, send an email to spockframewor...@googlegroups.com.
To post to this group, send email to spockfr...@googlegroups.com.
Visit this group at http://groups.google.com/group/spockframework.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Sebastian Gozin

unread,
Jul 16, 2013, 2:32:58 PM7/16/13
to spockfr...@googlegroups.com
While PowerMock is certainly capable of doing this I would like to stress that you should only mock static methods as a last recourse.
Mocking a static incurs an overhead of more than a second every time it is called so it could easily slow down your test suite to intolerable levels.

New Groovy

unread,
Jul 24, 2013, 3:26:42 PM7/24/13
to spockfr...@googlegroups.com
@Peter:  I'm struggling to figure out where to add the new Expections() {{...}} block?  If I add it under setup, when, or then I always get:

java.lang.IllegalStateException: Invalid place to record expectations

Thoughts?  I'm using the first example here: http://jmockit.googlecode.com/svn/trunk/www/tutorial/AnExample.html

Peter Niederwieser

unread,
Jul 24, 2013, 3:46:40 PM7/24/13
to spockfr...@googlegroups.com
I've never ever used PowerMock or JMockit, but setup-block sounds right. If you can't get it to work, first try with a JUnit test written in Java, then with a JUnit test written in Groovy, to sort out any problem unrelated to Spock.

Cheers,
Peter

New Groovy

unread,
Jul 24, 2013, 4:22:20 PM7/24/13
to spockfr...@googlegroups.com
Hi Peter,

I did both, and they both worked fine...

But putting the new Expectations block anywhere causes the error I originally posted...

Any thoughts on how to figure this out?

If someone wants to play with it, just add JMockit dependency, and then for a class (MyClass) with a static method, in a spec add the following class a class attribute:

   @Mocked MyClass unused

and in your test method:

   new Expectations() {{
       MyClass.myStaticMethod()
       result = null
   }}


Peter Niederwieser

unread,
Jul 24, 2013, 4:35:42 PM7/24/13
to spockfr...@googlegroups.com
I don't understand. Are you saying that you got JMockit in general, and `new Expectations() { … }` in particular, to work with JUnit+Java, JUnit+Groovy, but not with Spock?

Looking at your code snippet below, I wonder how the field annotated with `@Mocked` is supposed to get injected. Does JMockit require a special JUnit runner? Is the test class itself getting transformed? Maybe JMockit makes some assumptions about JUnit tests that don't hold under Spock. Have you asked for help on the JMockit list?

Cheers,
Peter

New Groovy

unread,
Jul 24, 2013, 5:07:52 PM7/24/13
to spockfr...@googlegroups.com
HI Peter,


> Are you saying that you got JMockit in general, and `new Expectations() { … }` in particular, to work with JUnit+Java, JUnit+Groovy, but not with Spock?
Exactly.  I wrote a simple JUnit test in Java, then in Groovy, and the new Expectations() block worked fine in both.


> I wonder how the field annotated with `@Mocked` is supposed to get injected
I'm new to JMockit, but I don't think the field gets injected - I think JMockit just uses it to create the Mock.  This from the page I pointed you to:

"Other mocking tools usually require a call to some mock creation method, which always returns a new object which later needs to be passed to the code under test. In JMockit, such instances may be passed to code under test, but don't have to be. In fact, no instance may be used at all, like in the case of final Database unused = null; used in the example tests."


> Does JMockit require a special JUnit runner?
I'm just running the tests that worked with regular old JUnit.  I don't know about transformation or assumptions - I do know it's supposed to work fine with TestNG.


>Have you asked for help on the JMockit list?
And I have already posted on the JMockit mailing list - haven't seen any responses yet.

The problem is I am not an expert either on Spock internals, though I use it a lot.

Whatever thoughts you have are appreciated...


Peter Niederwieser

unread,
Jul 24, 2013, 5:33:11 PM7/24/13
to spockfr...@googlegroups.com
JMockit must somehow process the test class, otherwise the `@Mocked` annotation wouldn't have any effect. Chances are that for whatever reason, that processing fails when using Spock. As I'm not familiar with how JMockit processes test classes, I can't say more than that.

Cheers,
Peter

New Groovy

unread,
Jul 25, 2013, 2:45:04 PM7/25/13
to spockfr...@googlegroups.com
HI Peter,

Still trying to get details from the JMockit list...

However, I did figure out that if I use their Mockups Api, I can just declare something like the following, and there are no issues with Spock.

 // Define and apply a mock-up before exercising the code under test:
 new MockUp<SomeClass>() {
    @Mock int someMethod(int i) { assertTrue(i > 0); return 123; }
    @Mock(maxInvocations = 2) void anotherMethod(int i, String s) { /* validate arguments */ }
 };


Billy Yarosh

unread,
Feb 9, 2015, 8:29:11 PM2/9/15
to spockfr...@googlegroups.com
Mockups do work, but personally I have had issues where the mockup will not teardown after a test completes. Even if explicitly calling .tearDown() on the MockUp instance the mock still persists. I would suggest avoid JMockit with spock tests.
Reply all
Reply to author
Forward
0 new messages