My take on it for Grails 3.x, based on the other answers and nicely wrapped in a trait for easy reuse:
BaseUrl.groovy
/**
* Exposes the {@code baseUrl} property for integration and functional tests, i.e. {@code http://<host>:<port><contextPath><path>}, where
* {@code path} is optionally provided by implementing classes by overriding the {@link #getPath()} method.<br><br>
*
* <b>Please note</b> that this trait requires {@code grailsApplication} to be present on the implementing class. This may be achieved
* by annotating the test class with {@code @TestFor(...)}.
*
* @author Michael Jess (http://stackoverflow.com/users/1821301/michael-jess)
*
*/
trait BaseUrl {
/**
* Retrieves the grails link generator
*
* @return the {@code grailsLinkGenerator} bean
*/
private def getGrailsLinkGenerator() {
assert grailsApplication, "grailsApplication not set, did you forget the @TestFor annotation?"
grailsApplication.mainContext.getBean("grailsLinkGenerator")
}
/**
* Returns the server base URL as provided by the link generator
*
* @return The server base url ({@code http://<host>:<port>})
*/
private def getServerBaseUrl() {
getGrailsLinkGenerator().serverBaseURL
}
/**
* Returns the context path as provided by the link generator
*
* @return The context path (e.g. {@code /<appName>} pre-grails 3.x)
*/
private def getContextPath() {
getGrailsLinkGenerator().contextPath
}
/**
* Returns the grails application base URL
*
* @return The grails application base URL ({@code http://<host>:<port><contextPath><path>})
*/
def getBaseUrl() {
getServerBaseUrl() + getContextPath() + getPath()
}
/**
* Returns the path of the current controller under test. Should be overridden by test classes.
*
* @return The controller path fragment
*/
def getPath() { "" }
}
Just implement it like so:
@TestFor(MyController)
class MyControllerSpec extends Specification implements BaseUrl {
@Override
def getPath() { "/api/myController" }
...
And then in the test cases:
...
get("$baseUrl/you/name/it")
...