Imo there's zero difference between 'thousands of microservices' and 'one monolith with thousands of functions/classes/etc' in terms of effort required to make it correct - both are still tiny interconnected pieces making up a whole, and you can separately unit test a function just as easily as you can separately e2e test a single microservice.
They still make up some whole product that presumably does something as a whole that you actually care about, and the complexity inherent to that doesn't go away with either approach.
Have you had to deal with a microservices environment? Because there's significantly more operational and architectural complexity with a distributed system compared to a monolith. Now you have to deal with reliability, retries/backoffs, versions, distributed transactions, consistency issues, service discovery, idempotency, and a million other things. I would generally not recommend adding all this overhead unless absolutely necessary. Or at least that was the recommendation pre-AI, but I don't think I've changed my mind on it yet.
Sure there is. For thousands of classes/functions, I can test the boundaries between them in nanoseconds each. Integration tests are the important part, because with the quality of AI coding these days, unit testing is a waste of time.
With micro services, that same function call is now a minimum of 200us. And now I have LOC for serialization/deserialization, retries, error handling, etc, bloating my code and making it harder to understand, plus now to do the same integration test I need to understand N different build systems for each component.
1 difference (out of many, many, differences), is that (most) compilers don't make guarantees across process boundaries.
In fact microservices are arguably more complex. It is the reason why microkernels have not succeeded compared to monolith till now.
The separation in micro services is hard to break though. You need to add an API on one side and a call on the other.
In a monolith it's significantly easier to do something that has an unexpected impact somewhere else. For example, changing a shared object a singleton to a clone will give you race conditions all over the place. You just don't have that footgun in micro services.