Most of the integration tests are for happy paths, i.e. ones where you can catch the obvious regressions. Testing corner cases is much more troublesome, because you have to set up a whole lot of specifics in multiple services. These are much easier to simulate with mocks.
Mind you, I hate unit tests for specific functions: I much prefer them as component tests, where you start with the inputs to the module and check the outputs and calls outside of the module. These ease refactoring where you actually change the underlying code and without changing the unit tests, you know that you also handled all those pesky corner cases.
Unit tests are less valuable for testing applications because the unit tests end up just being mirrors of your application classes/functions and you have to make changes in 2 places now any time you need to tweak application logic.
For applications I think black box tests have the highest ROI. Your application should have a headless mode through which you can send all of your test cases (real life inputs) and verify the output of your app has expected shape/value. As you encounter issues from user feedback, simply add to your list of black box tests. The beauty is that down the road you can "rewrite your app in Rust" or whatever and you'll have a huge set of black box regression tests you can use to validate the rewrite.
But at the other end of the spectrum (say, php), things are very different. You want that code exercised, just to be confident that it will actually do something, anything. Even if the question wether those things it does are right or wrong is left to higher level tests.
You should prefer to instantiate your class with real objects, if you can’t do that then use fakes, as a very last resort you can use a mock but at that point your test is probably useless.
(The exception) If you have an class that is a wrapper around some HTTP requests, then it is fine to mock these HTTP calls. If you have a test that depends on this class, then you can use either mock these calls again, or upgrade to a fake if the mocking is too complex.
How could it possibly be that unit tests are "good" or "bad" in general, for all software development?
Integration tests are better at accurately reflecting the real software. There is less of a leap of faith between "this test passes" and "the software actually works".
Unit tests are better at telling you exactly what failed. There is less of a research project between "this test fails" and "this code right here needs to be fixed".
I don't really love anxiety-inducing leaps of faith or time-consuming research projects, but I don't know of one form of testing that avoids both.
I write unit tests only if the logic is completely encapsulated by the "unit". The less you need to mock, the higher value the tests bring. That's one of the reasons I prefer to work on monoliths, it's much easier to test almost-end-to-end.