3

How would you fake a session value in functional test in Play Framework 1.2.3?

I'm doing a simple test like:

Before running the test, I set up a blank session, hoping it will make part of the test:

@Before
public void setupHTTP() {
   Session.current.set(new Session());
}
@Test
public void testRedirectToUserHomeForAuthenticatedUserWhenBlankAction() {
    authenticateUser("test@user.com");
    Response response = GET("/user/blank");
    assertRedirected(response, "/user/home");
}

The method

authenticate(String userEmail)
just put the key "username" in the session map:
protected void authenticateUser(String userEmail) {
        // Put in session the email
        Session.current.get().put(USERNAME, userEmail);
}

But the test runs in a different thread, as long as I could understand, and don't see the session I've set up...

How to fake session values in functional tests?

Joao Pereira
  • 2,454
  • 4
  • 27
  • 35

2 Answers2

3

I had the same problem, but in tests with Play 2.0.4.

I solved the problem by following Seb and Codemwnci answers and I built, checking API, the following solution:

@Test
public void listSomething() {
    running(fakeApplication(inMemoryDatabase()), new Runnable() {
        @Override
        public void run() {
            // LOGIN
            final Map<String, String> data = new HashMap<String, String>();
            data.put("email", "user@domain.com");
            data.put("password", "userpassword");

            Result result = callAction(
            controllers.routes.ref.Application.authenticate(),
            fakeRequest().withFormUrlEncodedBody(data));

            // RECOVER COOKIE FROM LOGIN RESULT
            final Cookie playSession = play.test.Helpers.cookie("PLAY_SESSION",
                                                                result);

            // LIST SOMETHING (using cookie of the login result)
            result = callAction(controllers.routes.ref.Application.list(), 
                                fakeRequest().withCookies(playSession));

            /* 
             * WAS RECEIVING 'SEE_OTHER' (303) 
             * BEFORE RECOVERING PLAY_SESSION COOKIE (BECAUSE NOT LOGGED IN).
             *
             * NOW, EXPECTED 'OK'
             */ 
            assertThat(status(result)).isEqualTo(OK); 
            assertThat(contentAsString(result)).contains(
                    "Something found");
        }
    });
}

The Application.list() is something like this:

@Security.Authenticated(Secured.class)
public static Result list() {
   return ok(list.render(...));
}
Community
  • 1
  • 1
Roberto
  • 500
  • 5
  • 9
2

Why do you want to fake, you can authenticate a user and work with its session in a functional test by carrying cookies between requests.

Something like

Response response = makeRequest(...); // connexion request
Request request = newRequest(...);  // new request
request.cookies = response.cookies

by getting the cookies of the previous response you carry your session

Seb Cesbron
  • 3,823
  • 15
  • 18
  • Hi Seb, my action in controllers should behave differently in case of having a authenticated user or not. Anyhow, I didn't understood well your answer, can you explain further how to set values in session during the functional tests? Thanks – Joao Pereira Nov 14 '11 at 10:17
  • my solution is not to put values in session but to really authenticate the user thus your functional test will behave exactly in the same way as if a user use your application – Seb Cesbron Nov 14 '11 at 15:20
  • You're right. I was trying to test something without having the authentication implemented yet, but functional tests should test the integration of the various parts of the system. I've just implemeted the authentication, make a POST("/login", params) and then after I can make any other request, which are now authenticated. Thanks. – Joao Pereira Nov 14 '11 at 16:30