Every Micronaut test that boots an EmbeddedServer sets micronaut.server.port = -1, which makes Micronaut draw a random port with SocketUtils rather than taking an OS-assigned ephemeral one. From micronaut-core 5.1.10:
MIN_PORT_RANGE = 1025
MAX_PORT_RANGE = 65535 // picked with java.util.Random
That range covers ports other processes hold. On macOS, ControlCenter (AirPlay Receiver) listens on 5000 and 7000 and answers 403 to any HTTP request:
$ lsof -nP -iTCP -sTCP:LISTEN
ControlCe *:5000
ControlCe *:7000
$ curl -o /dev/null -w "%{http_code}" http://localhost:5000/v1/query
403
Seen once in a full bazel test //... --nocache_test_results run:
FAIL: //domains/games/apis/one_d4:...api/QueryErrorWireTest
wellFormedQuery_returns200()
org.opentest4j.AssertionFailedError: expected: 200 but was: 403
one_d4 has no 403 path in its sources, and the run's log carries no query_event for that request though every other method in the class logged one — the request never reached the application.
Not reproduced in 57 further executions, which matches a ~2-in-64k draw per server boot. 18 test classes use this setting, so the exposure is the whole embedded-server suite, not one test.
What is not established: Micronaut probes a port before binding, so a draw of 5000 should have been rejected. How getPort() came to report a port ControlCenter owns is untraced — the probe/bind window is the place to look.
Fix direction: bind an OS-assigned ephemeral port and read back the real bound port, instead of the random-range picker.
Every Micronaut test that boots an
EmbeddedServersetsmicronaut.server.port = -1, which makes Micronaut draw a random port withSocketUtilsrather than taking an OS-assigned ephemeral one. Frommicronaut-core5.1.10:That range covers ports other processes hold. On macOS, ControlCenter (AirPlay Receiver) listens on 5000 and 7000 and answers 403 to any HTTP request:
Seen once in a full
bazel test //... --nocache_test_resultsrun:one_d4 has no 403 path in its sources, and the run's log carries no
query_eventfor that request though every other method in the class logged one — the request never reached the application.Not reproduced in 57 further executions, which matches a ~2-in-64k draw per server boot. 18 test classes use this setting, so the exposure is the whole embedded-server suite, not one test.
What is not established: Micronaut probes a port before binding, so a draw of 5000 should have been rejected. How
getPort()came to report a port ControlCenter owns is untraced — the probe/bind window is the place to look.Fix direction: bind an OS-assigned ephemeral port and read back the real bound port, instead of the random-range picker.