Play framework & CAS - 如何登录功能测试?
Posted
技术标签:
【中文标题】Play framework & CAS - 如何登录功能测试?【英文标题】:Play framework & CAS - How to log in for functional tests? 【发布时间】:2012-08-13 14:55:22 【问题描述】:我正在使用带有 CAS 3.1 的 Play 1.2.4 作为安全模块。在开发过程中一切正常,我必须登录才能使用我的控制器方法。
但我无法让日志部分在我的功能测试中工作。我用这个问题作为参考: Playframework Secure module: how do you "log in" to test a secured controller in a FunctionalTest?
我的测试如下所示:
@Test
public void testThatIndexPageWorks()
final Map<String, String> loginUserParams = new HashMap<String, String>();
loginUserParams.put("login", "foobar");
loginUserParams.put("password", "foobar");
final Response loginResponse = POST("/@cas/authenticate", loginUserParams);
final Request request = newRequest();
request.cookies = loginResponse.cookies; // makes the request authenticated
request.url = "/";
request.method = "GET";
final Response response = makeRequest(request);
assertIsOk(response);
测试在 "POST("/@cas......)" 行失败,但有以下异常:
java.lang.RuntimeException: java.util.concurrent.ExecutionException: play.exceptions.ActionNotFoundException: Action null?ticket=ST-e71ba57f-3f1f-4b71-b16f-0141db78b42f not found
at play.test.FunctionalTest.makeRequest(FunctionalTest.java:299)
at play.test.FunctionalTest.makeRequest(FunctionalTest.java:305)
at play.test.FunctionalTest.POST(FunctionalTest.java:152)
at play.test.FunctionalTest.POST(FunctionalTest.java:200)
at play.test.FunctionalTest.POST(FunctionalTest.java:167)
at ApplicationTest.testThatIndexPageWorks(ApplicationTest.java:53)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at play.test.PlayJUnitRunner$StartPlay$2$1.evaluate(PlayJUnitRunner.java:105)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at play.test.PlayJUnitRunner.run(PlayJUnitRunner.java:55)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:24)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
at org.junit.runner.JUnitCore.run(JUnitCore.java:136)
at org.junit.runner.JUnitCore.run(JUnitCore.java:117)
at play.test.TestEngine.run(TestEngine.java:112)
at controllers.TestRunner.run(TestRunner.java:66)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at play.mvc.ActionInvoker.invokeWithContinuation(ActionInvoker.java:548)
at play.mvc.ActionInvoker.invoke(ActionInvoker.java:502)
at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:478)
at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:473)
at play.mvc.ActionInvoker.invoke(ActionInvoker.java:161)
at play.server.PlayHandler$NettyInvocation.execute(PlayHandler.java:257)
at play.Invoker$Invocation.run(Invoker.java:278)
at play.server.PlayHandler$NettyInvocation.run(PlayHandler.java:235)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:98)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:206)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
Caused by: java.util.concurrent.ExecutionException: play.exceptions.ActionNotFoundException: Action null?ticket=ST-e71ba57f-3f1f-4b71-b16f-0141db78b42f not found
at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:232)
at java.util.concurrent.FutureTask.get(FutureTask.java:91)
at play.test.FunctionalTest.makeRequest(FunctionalTest.java:286)
... 57 more
Caused by: play.exceptions.ActionNotFoundException: Action null?ticket=ST-e71ba57f-3f1f-4b71-b16f-0141db78b42f not found
at play.mvc.ActionInvoker.getActionMethod(ActionInvoker.java:590)
at play.mvc.Controller.redirect(Controller.java:555)
at play.mvc.Controller.redirect(Controller.java:532)
at play.mvc.Controller.redirect(Controller.java:501)
at controllers.modules.cas.MockServer.loginAction(MockServer.java:51)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at play.mvc.ActionInvoker.invokeWithContinuation(ActionInvoker.java:548)
at play.mvc.ActionInvoker.invoke(ActionInvoker.java:502)
at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:478)
at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:473)
at play.mvc.ActionInvoker.invoke(ActionInvoker.java:161)
at play.test.FunctionalTest$1.execute(FunctionalTest.java:269)
at play.Invoker$Invocation.run(Invoker.java:278)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
... 3 more
Caused by: java.lang.Exception: Controller controllers not found
... 22 more
因为我得到了某种票,所以身份验证本身似乎有效。
有谁知道我如何在功能测试中通过 CAS 登录我的应用程序,或者在运行测试时同时禁用 CAS / @With(SecureCAS.class)?
【问题讨论】:
虽然有点晚,但可能对其他人有用...见***.com/a/18604839/1579667,和这个人有同样的问题和同样的答案。 【参考方案1】:设置 CAS 以使用 MockServer 进行播放测试配置文件,在 application.conf 添加:
%test.cas.mockserver=true
然后
@Test
public void testThatIndexPageWorks()
// test with cas functionality
final Map<String, String> loginUserParams = new HashMap<String, String>();
loginUserParams.put("login", "foobar");
loginUserParams.put("password", "foobar");
loginUserParams.put("serviceUrl", "modules.cas.securecas/authenticate"); // must be set but is not used
final Response authenticateResponse = POST("/@cas/authenticate", loginUserParams);
// you get a redirect to the authenticate service: assertEquals(Integer.valueOf(302), authenticateResponse.status);
// extract the ticket from the redirect url:
String location = authenticateResponse.getHeader("Location");
String ticket = location.substring(location.indexOf("ticket=")+7, location.length());
Logger.debug("ticket: "+ticket);
// odd workaround: we have to set the port and create the request by ourself, otherwise play is calling the url without port!
final int port = Http.Request.current() == null ? 80 : Http.Request.current().get().port;
final Request authenticateRequest = newRequest();
authenticateRequest.port = port;
final Response validateResponse = GET(authenticateRequest, "/modules.cas.securecas/authenticate?service=cas/serviceValidate&ticket="+ticket);
// the response is again a redirect, normally to the initially called page: assertEquals(Integer.valueOf(302), authenticateResponse.status);
Logger.debug("Authentication successfull");
// functional test of a html page:
final Request request = newRequest();
request.url = "/";
request.cookies = validateResponse.cookies; // makes the request authenticated
request.method = "GET";
final Response response = makeRequest(request);
assertIsOk(response);
【讨论】:
以上是关于Play framework & CAS - 如何登录功能测试?的主要内容,如果未能解决你的问题,请参考以下文章
Play Framework Routes 中的 Scala 反引号
Play Framework 1.2.4:#select 模板的选定选项
从 Play Framework 更改 WS API! 2.4 至 2.5