[2.1.1-java] How can I mock async and Promises for testing

1,620 views
Skip to first unread message

EduP

unread,
Jun 20, 2013, 7:40:13 AM6/20/13
to play-fr...@googlegroups.com
Hi,

We have some controllers that make async calls to a backend:

  public static Result foo() {
   
// some previous code
    WSRequestHolder request = WS.url(backendUrl);
   
return async(

      request
.get().map(
       
new Function<WS.Response, Result>() {
         
public Result apply(WS.Response response) {
           
// some callback code to process the response
           
return ok(Json.toJson(someObject));

         
}
       
}
     
)
   
);
 
}

In order to test them and work with TDD, we would like to write some tests that mock the backend invocations.

  • Can we mock WSRequestHolder or WS.Response someway?
  • I believe specs2 makes that possible for Scala. Can it be used with Java controllers?

Thanks in advance.

ChrisDebug

unread,
Feb 13, 2014, 2:08:02 AM2/13/14
to play-fr...@googlegroups.com
Hi!

Did you you ever get a solution for this?

Eric Torreborre

unread,
Feb 17, 2014, 9:59:06 PM2/17/14
to play-fr...@googlegroups.com
Did you try to use Mockito for this?

Eric.

RandomSpark

unread,
Feb 28, 2014, 12:56:27 AM2/28/14
to play-fr...@googlegroups.com
We have done Framework Wrappers i.e. any framework specific code e.g. WS or Messages are wrapped and we can easily mock the wrappers. For WS especially, we test the Wrapper with a dummy http service. This is a very common pattern so you can create a common library to be used across play projects.

Shripad

ChrisDebug

unread,
Feb 28, 2014, 12:47:10 PM2/28/14
to play-fr...@googlegroups.com
Thanks for the wrapping idea but I'm still not that clean on it. Do you think you can give me an example of wrapping WS.Response or point me to some urls that could help?

Is this the general idea?

public class WSResponseWrapper extends WS.Response {
    ...
}

Alberto Souza

unread,
Feb 28, 2014, 1:49:34 PM2/28/14
to play-fr...@googlegroups.com
This code is tricky to be mocked. It is a static call and libs around there, like Mockito, do not support this feature. Maybe PowerMock can help you. Here a example of code:

@RunWith(PowerMockRunner.class)

@PrepareForTest({ WS.class })

public class ApplicationTest {


  @Test

  public void mockWsCall() {

    mockStatic(WS.class);

     Mockito.when(WS.url("http://www.google.com")).thenReturn(new MyRequestHolder("http://www.google.com"));

    }

   public static class MyRequestHolder extends WSRequestHolder{

         public MyRequestHolder(String url) {

           super(url);

           System.out.println("my holder");

        }

    }

   }

In your build.sbt add the following lines:

  "org.powermock" % "powermock-core" % "1.5.4",

  "org.powermock" % "powermock-module-junit4" % "1.5.4",

  "org.powermock" % "powermock-api-mockito" % "1.5.4"


PowerMock is a nice alternative to mock Static behavior...

http://alots.wordpress.com
https://leanpub.com/playframeworknapratica

Will Sargent

unread,
Feb 28, 2014, 1:57:51 PM2/28/14
to play-fr...@googlegroups.com
I'd go for jMockit: https://code.google.com/p/jmockit/

You will be able to mock out WSRequest in 2.3, but for now the best thing you can do is to hide WS behind a service and mock out access to the service.  This will also help when you need to break apart your unit tests from your integration tests.

Will Sargent
Consultant, Professional Services
Typesafe, the company behind Play Framework, Akka and Scala


--
You received this message because you are subscribed to the Google Groups "play-framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framewor...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Alberto Souza

unread,
Feb 28, 2014, 2:15:16 PM2/28/14
to play-fr...@googlegroups.com
Nice!. But, even with the service isolated in a class, the access still is static.

Will Sargent

unread,
Feb 28, 2014, 2:23:36 PM2/28/14
to play-fr...@googlegroups.com
On Fri, Feb 28, 2014 at 11:15 AM, Alberto Souza <alot...@gmail.com> wrote:
Nice!. But, even with the service isolated in a class, the access still is static.

It shouldn't be.

trait TwitterService {
  def getTweets : Future[Seq[Tweet]]

class WSTwitterService extends TwitterService {
   def getTweets = {
       WS.url("...").get().map { response => parseTweets(response.json) }
   } 
}

class StubTwitterService extends TwitterService {
    def getTweets = { Future.successful(Tweet()) }
}

val stubTwitterService = new StubTwitterService()

val mockTwitterService = mock[TwitterService]

ChrisDebug

unread,
Feb 28, 2014, 2:30:23 PM2/28/14
to play-fr...@googlegroups.com
@Shripad: Thanks for the example! I'll definitely try this. I've been successfully using PowerMock for a few of my static methods so I'll try it here as well.

@Will: Thanks for the info as well. I can't wait for 2.3 to make my unit testing life easier. =)

Chris

unread,
Jan 16, 2015, 3:08:53 PM1/16/15
to play-fr...@googlegroups.com
How would I do this in 2.3?
Reply all
Reply to author
Forward
0 new messages