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 in prior to testing my controller (otherwise I will be redirected to the login page).
I've tried to log in prior to calling a secured action. Here's what my FunctionalTest looks like:
@Test
public void someTestOfASecuredAction() {
Map<String, String> loginUserParams = new HashMap<String, String>();
loginUserParams.put("username", "admin");
loginUserParams.put("password", "admin");
// Login here so the following request will be authenticated:
Response response = POST("/login", loginUserParams);
// The following is an action that requires an authenticated user:
Map<String, String> params;
params.put("someparam", "somevalue");
response = POST("/some/secured/action", params);
assertIsOk(response); // this always fails because it is a 302 redirecting to /login
}
Stepping through the code, I've verified that the login post works - it causes a redirect response with location set to the home page (which indicates a successful login).
But then in the subsequent call to a secured action, I am always redirected to the "/login" page - indicating that my previous login did not stick for the second POST request.
Looking into the source code of FunctionalTest I saw there was an @Before interceptor that clears all cookies. I tried overriding this intercepter in my own intermediary superclass (to preserve the cookies), but that didn't work either.
EDIT: I was confusing the play.mvc.Before interceptor with org.junit.Before - the former for use with Play! controllers, the latter for JUnit tests. The @Before in the FuncitonTest is a JUnit interceptor, so it should have any affect on cookies (since it gets run once prior to the test being run).
I do not want to have to write a Selenium test for every secured action - since almost all will be secured. Is there a way to "fool" the Secure module into believing you're authenticated? Or maybe some other very obvious way for handling this (seemingly common) scenario in a FunctionalTest?
Thanks in advance,
Mark
EDIT: Working code, Codemwnci's answer marked as correct
Codemwnci's answer is correct. Here is my workaround for preserving the cookies from one request to the next:
@Test
public void someTestOfASecuredAction() {
Map<String, String> loginUserParams = new HashMap<String, String>();
loginUserParams.put("username", "admin");
loginUserParams.put("password", "admin");
Response loginResponse = POST("/login", loginUserParams);
Request request = newRequest();
request.cookies = loginResponse.cookies; // this makes the request authenticated
request.url = "/some/secured/action";
request.method = "POST";
request.params.put("someparam", "somevalue");
Response response = makeRequest(request);
assertIsOk(response); // Passes!
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With