Problem
I have an app that uses CAS (Central Authentication Service) login. In the configuration (application.yml
), CAS is configured as follows:
grails:
plugin:
springsecurity:
# ...other configurations omitted ...
cas:
serverUrlPrefix: "https://<some endpoint for the actual CAS>"
serviceUrl: https://localhost:8443/myapp/login/cas
# ...other configurations omitted ...
When running functional tests, a Tomcat server is initiated with random port number, e.g. http://localhost:45359
and it is always changing with each run.
It seems like the app gets redirected to the CAS serviceUrl
after login, and normally my app runs on port 8443, so it's never a problem. But since the functional test brings up the Tomcat server at random port number, the redirection fails.
Also, I'm running my app using run-app -https
(i.e. https://localhost:8443
), but the test runs on http
(e.g. http://localhost:12345
). I don't know if this is an important detail or not.
The Test
My functional test goes as follows:
localhost:8443
.Source (based on: https://github.com/grails-guides/grails-test-security/blob/master/complete/src/integration-test/groovy/grails/test/security/AnnouncementControllerSpec.groovy):
@Integration
class MyAppControllerFunctionalSpec extends GebSpec {
def setup(){
}
def cleanup() {
}
void "test something"() {
when:"The home page is visited"
go '/myapp' // 1
then:"The title is correct"
title == "Login Page" // 2
at LoginPage // a helper class - subclass of geb.Page.
// Contains implementation of login method
when: "Sign in"
login('username', 'password') // 3 & 4 --> 5
then: "Title"
title == "Welcome MyApp"
}
Stacktrace:
java.lang.RuntimeException: org.apache.http.conn.HttpHostConnectException: Connect to localhost:8443 [localhost/127.0.0.1] failed: Connection refused (Connection refused)
at com.gargoylesoftware.htmlunit.WebClient.download(WebClient.java:2067)
at com.gargoylesoftware.htmlunit.html.HtmlForm.submit(HtmlForm.java:138)
at com.gargoylesoftware.htmlunit.html.HtmlButton.doClickStateUpdate(HtmlButton.java:97)
at com.gargoylesoftware.htmlunit.html.DomElement.click(DomElement.java:786)
at com.gargoylesoftware.htmlunit.html.DomElement.click(DomElement.java:733)
at org.openqa.selenium.htmlunit.HtmlUnitMouse.click(HtmlUnitMouse.java:74)
at org.openqa.selenium.htmlunit.HtmlUnitWebElement.click(HtmlUnitWebElement.java:151)
at geb.navigator.NonEmptyNavigator.click(NonEmptyNavigator.groovy:437)
at geb.content.TemplateDerivedPageContent.click(TemplateDerivedPageContent.groovy:115)
at myapp.LoginPage.login(LoginPage.groovy:22)
at geb.Browser.methodMissing(Browser.groovy:207)
at geb.spock.GebSpec.methodMissing(GebSpec.groovy:56)
at myapp.MyAppControllerFunctionalSpec.test something(MyAppControllerFunctionalSpec.groovy:39)
Caused by: org.apache.http.conn.HttpHostConnectException: Connect to localhost:8443 [localhost/127.0.0.1] failed: Connection refused (Connection refused)
at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:158)
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:353)
at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:380)
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236)
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184)
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88)
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:71)
at com.gargoylesoftware.htmlunit.HttpWebConnection.getResponse(HttpWebConnection.java:179)
at com.gargoylesoftware.htmlunit.WebClient.loadWebResponseFromWebConnection(WebClient.java:1321)
at com.gargoylesoftware.htmlunit.WebClient.loadWebResponseFromWebConnection(WebClient.java:1379)
at com.gargoylesoftware.htmlunit.WebClient.loadWebResponse(WebClient.java:1238)
at com.gargoylesoftware.htmlunit.WebClient.download(WebClient.java:2063)
... 12 more
Caused by: java.net.ConnectException: Connection refused (Connection refused)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:337)
at com.gargoylesoftware.htmlunit.httpclient.HtmlUnitSSLConnectionSocketFactory.connectSocket(HtmlUnitSSLConnectionSocketFactory.java:189)
at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:141)
... 25 more
Question
What is the correct way to make it so my functional tests can get past the CAS login?
Other Info
UPDATE
I have tried setting port numbers using an environment variable, to no avail. See: this Grails isssue
My current solution to get the functional test to run with CAS login from Intellij IDEA:
src/integration-test/groovy/<package>/
directoryRun the test from the IDE's Terminal:
grails test-app package.test_class --integration
For example, with package: foo
and test class MyAppControllerFunctionalSpec
:
grails test-app foo.MyAppControllerFunctionalSpec --integration