I want to write test for my controller:
Result changeAction = callAction(controllers.routes.ref.Users.changePassword());
assertThat(status(changeAction)).isEqualTo(OK);
I have a http status code - 300.
That's right it is redirect because I have a class named Secured
package controllers;
import play.mvc.*;
import play.mvc.Http.*;
public class Secured extends Security.Authenticator {
@Override
public String getUsername(Context ctx) {
return ctx.session().get("userId");
}
@Override
public Result onUnauthorized(Context ctx) {
return redirect(routes.Users.login(ctx.request().uri()));
}
}
And when I use the @Security.Authenticated(Secured.class)
annotation for controller method it redirects if session with "userId" do not exists.
So the question is, how can I fake the session?
I tried obviously call Controller.session("usderId", "2");
And got an exception:
java.lang.RuntimeException: There is no HTTP Context available from here.
at play.mvc.Http$Context.current(Http.java:30)
at play.mvc.Controller.session(Controller.java:54)
at play.mvc.Controller.session(Controller.java:61)
at controllers.UsersTest.testUnloginedChangePassword(UsersTest.java:35)
My question is: How to fake the session for controller?
And one additional question: how to test routes without using deprecated API, like Result result = routeAndCall(fakeRequest(GET, "/change_password"));
?
When unit testing controller logic, only the contents of a single action are tested, not the behavior of its dependencies or of the framework itself. Set up unit tests of controller actions to focus on the controller's behavior. A controller unit test avoids scenarios such as filters, routing, and model binding.
Mocking is used in unit tests to replace the return value of a class method or function. This may seem counterintuitive since unit tests are supposed to test the class method or function, but we are replacing all those processing and setting a predefined output.
Mock<ISession> sessionMock = new Mock<ISession>(); var key = "FY"; int fy = 2020; var value = new byte[] { (byte)(fy >> 24), (byte)(0xFF & (fy >> 16)), (byte)(0xFF & (fy >> 8)), (byte)(0xFF & fy) }; sessionMock. Setup(_ => _. TryGetValue(key, out value)). Returns(true);
A typical unit test contains 3 phases: First, it initializes a small piece of an application it wants to test (also known as the system under test, or SUT), then it applies some stimulus to the system under test (usually by calling a method on it), and finally, it observes the resulting behavior.
You can use the withSession(String, String)
method of fakeRequest
to put things in the Session. Note that this returns a fakeRequest
so you can chain that method if you need to put multiple keys in the session.
Your test could then look something like this:
@Test
public void test() {
running(fakeApplication(), new Runnable() {
public void run() {
String username = "Aerus";
Result res = route(fakeRequest("GET", "/")
.withSession("username", username)
.withSession("key","value"));
assert(contentAsString(res).contains(username));
}
});
}
Note also that I used the route
method and not routeAndCall
, the first is the replacement of the deprecated method.
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