PowerMock outside a Testing Framework

527 views
Skip to first unread message

Bryan Jacobs

unread,
May 2, 2011, 11:58:12 AM5/2/11
to PowerMock
Our application depends on an external web service. I have created a
mock implementation of the external web service so that we can provide
whatever data we need to test our application. Essentially you give
the mock implementation some xml data and then it will return that
based on which api calls you make

Because we have done this another problem that we have encountered is
the need to have new Date() or Calendar.getInstance() return a date
that matches our configured test data. Our data is very date
sensitive. For example, if a person is older than 18 but younger than
25 then do some logic. With all this date sensitive information we
need a way to control the server time to make data maintenance easier.
I don't want to have to change the time on the server because that
requires a lot of coordination with the teams that manage the
servers. Also, I don't want to create some utility class because if I
do that and people forget to use it then strange problems will occur.

Basically what I want to be able to do is have new Date() return
whatever date I tell it to in some configuration file. It appears
that I could mock out System.currentTimeMillis to make that happen.
Here is the part that makes it interesting. Selenium is doing
regression tests which means that the system will be running as if it
were in production. So I would like to find a way to make powermock
able to mock out the System.currentTimeMillis outside of a TestNG or
JUnit testing framework.

The question is how can I "bootstrap" powermock to run in a WAR file
that is actually deployed on a tomcat server?

While there are many ways to solve this problem, to me, this seems the
most elegant.

Bryan Jacobs

unread,
May 2, 2011, 7:17:41 PM5/2/11
to PowerMock
Let me see if I can state this more clearly....

I would I get powermock to work outside of Junit or Testng.

Example:

public class Example{

public static void main(String[] args){
mockStatic( System.class);

expect( System.currentTimeMillis() ).andReturn( 11111 );

Long time = System.currentTimeMillis(); // time is now 11111

}

}

This isn't a junit or testng class its just a class. There must be a
way to get PowerMock to understand this because, guessing here, JUnit
and TestNG modules had to be created to make it possible for them to
work with PowerMock magic.

Bryan Jacobs

unread,
May 2, 2011, 7:21:16 PM5/2/11
to PowerMock
Oops I missed the replayAll() method call....I hope this is more
clear....

Johan Haleby

unread,
May 3, 2011, 2:55:50 AM5/3/11
to powe...@googlegroups.com
Hi Bryan, 

I understand what you mean but I don't think that PowerMock is the best tool for this. I would probably use something like Aspectj myself. How ever it may be possible and it's quite interesting technically so perhaps we should trying adding some better support for it in the future. And mocking out System.currentTimeMillis() will be even trickier because it's a java system class. I released a new version of PowerMock yesterday that uses a Java agent to bootstrap and you can possibly try it out if you like but it won't be super-pretty. If possible I would recommend that you wrap System.currentTimeMillis() in your own static method that you stub with PowerMock. Otherwise go for Aspectj!
  1. Follow the instructions on this page to get the agent into the classpath.
  2. Initialize the Agent manually, possibly in a static constructor: PowerMock.initializeIfNeeded();
  3. PowerMockAgentTestInitializer.initialize(target.getClass());
  4. Stub the method using the MemberModification API in powermock-support.
Something like:

@PrepareForTest(SomeClass.class)
public class MyMethodStubber {

     public void stubMyMethodToReturnSomeValue() {
                PowerMockAgent.initializeIfNeeded();     
                PowerMockAgentTestInitializer.initialize(MyMethodStubber.class);
                stub(method(SomeClass.class, "myMethod")).toReturn("some value");
     }     
}

But for system classes this will be harder since you need to prepare all classes that interact with System.currentTimeMillis instead (refer to the blog).

Regards,
/Johan

--
You received this message because you are subscribed to the Google Groups "PowerMock" group.
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.


Bryan Jacobs

unread,
May 3, 2011, 11:15:48 PM5/3/11
to PowerMock
Thanks for the feedback I will try that out. I appreciate the time
you took with your response as well because I realize what I am doing
is pretty far out there.

Here is why I like powermock for this solution:

If powermock can work this way then you have the ability to mock out
anything that you need to in a running system.

In addition, when you use apectj I only want that behavior when we run
integration tests, so now I have to control that additional build
configuration.

With powermock all I have to do is set a flag in a file that I read in
which essentially tells me go generate the necessary mock
implementations. Specifically change Calendar.getInstance() and new
Date() to return the value that I tell them too....who said that time
travel isn't possible :)

I agree that aspectj is an option but IF powermock could do this IT
WOULD BE HUGE FOR ME!

Thanks Again,

Brayn



On May 3, 12:55 am, Johan Haleby <johan.hal...@gmail.com> wrote:
> Hi Bryan,
>
> I understand what you mean but I don't think that PowerMock is the best tool
> for this. I would probably use something like Aspectj myself. How ever it
> may be possible and it's quite interesting technically so perhaps we should
> trying adding some better support for it in the future. And mocking out
> System.currentTimeMillis() will be even trickier because it's a java system
> class<http://blog.jayway.com/2009/05/17/mocking-static-methods-in-java-syst...>.
> I released a new version of PowerMock yesterday that uses a Java agent to
> bootstrap and you can possibly try it out if you like but it won't be
> super-pretty. If possible I would recommend that you wrap
> System.currentTimeMillis() in your own static method that you stub with
> PowerMock. Otherwise go for Aspectj!
>
>    1. Follow the instructions on
> this<http://code.google.com/p/powermock/wiki/PowerMockAgent>page to
> get the agent into the classpath.
>    2. Initialize the Agent manually, possibly in a static constructor:
>    PowerMock.initializeIfNeeded();
>    3. PowerMockAgentTestInitializer.initialize(target.getClass());
>    4. Stub the method using the MemberModification API in powermock-support.
>
> Something like:
>
> @PrepareForTest(SomeClass.class)
> public class MyMethodStubber {
>
>      public void stubMyMethodToReturnSomeValue() {
>                 PowerMockAgent.initializeIfNeeded();
>                 PowerMockAgentTestInitializer.initialize(
> MyMethodStubber.class);
>                 stub(method(SomeClass.class, "myMethod")).toReturn("some
> value");
>      }
>
> }
>
> But for system classes this will be harder since you need to prepare all
> classes that interact with System.currentTimeMillis instead (refer to the
> blog).
>
> Regards,
> /Johan
>
Reply all
Reply to author
Forward
0 new messages