TL;DR: Testcontainers allows you to expose a host’s port to containers using Testcontainers.exposeHostPorts(localServerPort); .

A short reminder: for my Master’s thesis I have to work with Selenium docker containers to automate Twitter accounts. My latest task was to make it possible to specify a proxy, which should be used by the Chrome browser running inside a container. That way, it want to fool Twitter about the true origin of an account, which is especially interesting if you want to automate multiple accounts at the same time on the same machine.

While setting the proxy has to be done using Selenium’s JavascriptExecutor.executeScript(..) method in conjunction with JavaScript code accessing the Proxy API for Extensions (for more information, have a look at the example in spring-selenium-pool), I finally wanted to test my setup.

As a mock proxy server, I decided to use MockServer - integration with Java/Kotlin is easy, as is defining stub responses. The final question however was: how could I connect to the MockServer running on the host from inside the Selenium container?

Luckily, Testcontainers guys got me covered. The documentation provided the answer: Testcontainers.exposeHostPorts(localServerPort); .

That’s all we need. Just make sure to run that line before your container starts, but after the mock server is running.

The host will then be available from inside the container at host.testcontainers.internal + your random local port.

What I understood it does under the hood, is to start another Docker container with an ssh-server that uses port forwarding to route all TCP traffic from the container of interest through the ssh-container to the host.

So in the end, here is the skeleton of the resulting test:

@SpringBootTest(classes = [TaskWithProxyTest.App::class],
        webEnvironment = SpringBootTest.WebEnvironment.NONE,
        properties = ["selenium.pool.size=1"])
class TaskWithProxyTest {

    // causes the container from spring-selenium-pool to come up
    @SpringBootApplication
    class App

    companion object {

        lateinit var mockProxy: ClientAndServer

        @BeforeAll
        @JvmStatic
        fun first() {
            val mockServerPort = SocketUtils.findAvailableTcpPort()
            mockProxy = startClientAndServer(mockServerPort)

            // necessary to access mockserver from container
            Testcontainers.exposeHostPorts(mockServerPort)
        }

        @AfterAll
        @JvmStatic
        fun tearDown() {
            mockProxy.stop(true)
        }
    }

    @Test
    fun `
your test
`() {
        // ...
    }
}

This post is also available on DEV.