Tuesday, 8 March 2011

Testing your Play! controllers

Lets say you have a controller like this (from the Play! documentation)

package controllers;
import java.util.*;
import play.*;
import play.mvc.*;
import models.*;
public class Application extends Controller {
    public static void index() {
        Post frontPost = Post.find("order by postedAt desc").first();
        List olderPosts = Post.find(
            "order by postedAt desc"
        render(frontPost, olderPosts);

And you want to write a test to check the render parameters are correct, how do you do that?

Well here is a little example
public class ApplicationTest extends FunctionalTest{
 public void before() {

 public void testHomePageFirstPost() throws MalformedURLException {
  // Call the home page
  Response response = GET("/");
  // Verify that Matches.matchCreate() passed correct params to render().
  Post frontPost = (Post) getRenderParameter("frontPost");
  assertEquals(${value_from_yml}, frontPost.author.fullname);
  assertEquals(${value_from_yml}, frontPost.postedAt);

  * Gets the parameter that was passed to render() method.
  * @param key
  * @return
 public static Object getRenderParameter(String key) {
  RenderArgs current = Scope.RenderArgs.current();
  return current.data.get(key);


You might want to put the getRenderParameter in a separate class to easily reuse it.

If you want to test a controller method that take parameters is as easy.

Let's assume you want to test a simple controller method in Users called getUserByUsername to make sure the correct user is added to render when the form is submitted

public class Users extends Controller {
 * Gets the user given his username
    public static void getUserByUsername(String username) {
        User currentUser = User.find("byUsername", username).first();

In this case the test would be

public class UserLoginTest extends FunctionalTest{

 public void before() {
 public void testGetByUsername() {
  Map<String, String> params = new HashMap<String, String>();
  params.put("username", "user1");
  Response response = POST("/users/getbyusername", params, new HashMap<String, File>());
  User currentUser = (User) getRenderParameter(&quot;currentUser&quot;);
  assertEquals(${from_users.yml}, currentUser.name);
  assertEquals(${from_users.yml}, currentUser.email);

Please feel free to comment!



Dominik Dorn said...

the ${from_users.yml} isn't really in the code, right?

mericano1 said...

That's right. You need to have some data in the db.
I'm using Fixtures.load("users.yml"); to do that.
Let's assume your users.yml looks like this

name: myUser1
username: user1
email: myUser1@email.com

name: myUser2
username: user2
email: myUser2@email.com

Then you need to replace ${from_users.yml} with 'myUser1' in the first line and 'myUser1@email.com' in the last line.

Hope this clarifies.