laurence-myers
One man's bugfix is another man's breaking change. If product A implements a workaround for a bug in product B, but the bug gets fixed in a patch version, it could break product A's code, so it becomes a breaking change. The only way to anticipate these changes is reading the change logs/release notes, and thorough automated regression testing. (Obviously unfeasible for every dependency.)
Maybe versions should be a single number, like a build number. It just gets tricky when you have multiple versions out there, each requiring patches.
Save yourself some grief and use a service like CircleCI, it provides isolated (Docker) environments that are spun up per test run. It supports many languages and background services (like databases).
As for writing tests, you would be best to start writing them at a "system boundary". This might take the form of sending HTTP requests to your endpoints and parsing the response.