Published on

How to Debug a SpringBoot Test

Authors

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

You then 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.yaml or 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 MOCK the 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 netstat.

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.

MakingBreakpoint-Break-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.