EDIT: I\'m using Play! version 1.2 (production release)
I want to test controller actions that are secured by Secure module class, so I need to log
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(...));
}
Maybe you are seeing https://bugs.launchpad.net/play/+bug/497408
I think it is supposed to work.
Update: I did some debugging. I think there are two bugs.
So bug 1 breaks it if you don't set maxAge, and bug 2 breaks it if you do set maxAge.
Update 2: I made some patches that fix it for me: http://play.lighthouseapp.com/projects/57987-play-framework/tickets/775
I think there must be a misunderstanding of what the @Before interceptor does. It executes before your test is executed. If your test then logs you in, then this event happens AFTER the @Before code has been executed and the results of the secure module should be saved to the Cookie.
Therefore, I can only assume that the Cookie is not being sent with the following request, therefore, I would suggest trying the following...
get the cookie used by the secure cookie from the Response object immediately following your login. Create a Request object and set the Cookie to the request object, then call your POST method, passing in your request object.
I have not tested this code, so not sure how it is going to react to mixing a pre-built request object, and passing in a URL, but not sure what else to suggest.
Want to point out that there is an error in Mark S' final solution.
This is wrong: request.url = "/some/secured/action";
This is right: request.path = "/some/secured/action";
"url" should be a full url.