Design your interfaces and method signatures in a way which would minimize future need for changes.
For example, do not pass configuration options to your module as option1 and option2, instead wrap them in options/config object and pass that to your module.
This allows you to add more configuration options in the future without having to break any existing interface.
Finally, when it comes to brittle unit tests, an extra layer of functional / integration tests is what you should have.
These tests will be less brittle as they will break in more cases (i.e. if there is an issue on the edges of "units" of your codebase).
The tradeoff will be that functional/integration tests will be slower and more difficult to execute (I suggest using docker-compose to run integration tests in a platform agnostic way).
Sometimes you don't want to prevent change because it's an implementation detail. That can mean private APIs, but also whole layers of abstraction.
Common layering, for example, is:
1. Low level operation that needs to be stable, so needs tests.
2. Medium level abstraction layer, not core business logic and builds on stable layer.
3. High level abstraction, the exposed public business logic API. Public API so needs tests.
Medium layer does not necessarily need tests in this case.
I have a bit higher level discussion of this in a talk I gave in May (first video): https://codewithoutrules.com/talks/