- Published on
How to Debug a SpringBoot Test
- Yair Mark
Today I started looking at how to write the provider portion of a Pact test. The provider is the service that actually exposes the endpoint we are writing the Pact against. Part of running a Pact provider test involves running a test class using the
@SpringBootTest annotation as per the Pact Spring Provider test documentation. This means that the full blown application - using you test application.yaml - will be run to test the Pact. This makes sense as ideally we want to test the pact against the real endpoint or as close to the real endpoint as possible. But I kept running into issues while trying to run the pact. The main issue I had was that the Pact test would run but get a connection refused.
So as a starting point I wanted to first confirm that the SpringBoot test was running on the correct port. I simply added a break point in my test class and from there tried to work out the easiest way to determine this on Linux. It turns out you can use
netstat with the very memorable flag combination
peanut as below:
sudo netstat -peanut
grep out the port you are expecting your test application to be bound to (this should be the server.port you have setup in your test's
application.properties file). After running this I could see that the test was not running the app on the expected port. Looking more carefully at one of the Pact Spring provider test examples I saw the following line which is key:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
I went into the sources for this Spring enum and discovered that the default used (if no
webEnvironment is specified) is
MOCK which results in no real web app instance being run in your application. In case you are curious, when running a SpringBoot test with
server.port value used is
-1. You can debug this by autowiring in the Spring ApplicationContext and in debug mode in your test run
applicationContext.getProperty("server.port");. This is property that Spring uses to determine what port to use for the server. Ok awesome this explains why I cannot see my apps port running when checking with
The Pact provider tests now run but fail as the results are not as expected. A
200 is returned but Spring is redirecting all requests to
/login. So it appears there is some fiddling I need to do to get the authentication portion working as part of my tests. I originally thought that debugging this would be hard since as soon as I am on a breakpoint I cannot hit the running endpoint to debug.
After sitting with a colleague he showed me a nifty trick. What you do is you put your breakpoint down. On the line with the breakpoint you push
ctrl/cmd-shift-f8 or right click the breakpoint and where it has a radio button choose
Thread instead of
All. This will make the test stop at that breakpoint on a separate thread.
What this means is that you can keep the app running by letting it hit this breakpoint and then still run
curls against it to test further. Unfortunately I did not manage to resolve this issue today and will need to dig further tomorrow. I should by then have Pact working end to end without a broker in place. The broker will definitely come later but essentially what the broker does is hold the Pacts generated by the different consumers of an API and feeds that to the provider of the API to make sure nothing breaks.The more consumers you have with variations on the usage of the API the more pacts you end up with which can quickly become unmanageable if you need to store those in a directory on the provider hence the need for a broker.