Because for certain kind of project the strategy stops working.
I work as QE on a fairly large, ~7 years old project. Micorservice architecture has been attempted. We always merge to master, which means that everything more-or-less is a feature-branch merge. We have too many repositories to count.
And what we learned is, that most of the components we have are just too thin to allow for useful unit-test coverage. Almost everything is [Gui]--request->[Middleware]--request-->[Proxy]--request-->[Backend]->[Database].
In reality, [Middleware] and [Backend] probably should have been a single component, but devs wanted to do microservices, and be scalable, but they didn't really understand the bounded contexts of their services.
All of this leads us to a place, where unit-tests don't tell us much.
On the other hand, we managed to spawn [Middleware]->[Backend]->[Database], and we can run a useful integration tests-suite in ~2 minutes.
So, on one hand, if we desined this better, the good-old pyramid might be a working strategy. On the other hand, if I can get actual services running in minute, and test them end-to-end, I don't think I will bother with true unit-tests on my next projects. I.e. why mock the database, if I can spawn it seconds :-)
So, if I understand it correctly, Middleware and Backend should have been single component since it's one bounded context and splitting it makes one of those feature envy? Is there some benefit keeping these separate or is the cost of change too high at this point?
If it's not about features, but more about API, have you tried Consumer-driven contract testing approach?
The reason was, you can have more instances of backend for a single middleware and that should have helped with scalability.
If we had the resources to do the refactoring, we would probably end up with two-three different backends for various contexts, and without the middle-man between the gui and the backends.
On the other hand, the cost of change is probably too high, and most probably this version of our product will be kept on minimum-resource life support.
We are looking for doing consumer-driven testing for our new set of services we are working on.
The units tell you tons. They just don't tell you the whole story. Trust me, try complex distributed systems testing in an environment the underlying services themselves are bug-prone and issuing stack traces all over because of poor fencing/bounds checking/et al.
You may think that way now regarding mocking the database, but where you will find yourself down the line is trying to devise a functional system integration test case for a slightly esoteric condition (deadlocks, timeouts). It's nice to have the scaffolding of a unit testing framework with robust mocks for those situations.
Edit: also, you should consider a gitflow workflow (dev -> integration -> master/stable) and make feature branch off of dev to insulate your master.
I work as QE on a fairly large, ~7 years old project. Micorservice architecture has been attempted. We always merge to master, which means that everything more-or-less is a feature-branch merge. We have too many repositories to count.
And what we learned is, that most of the components we have are just too thin to allow for useful unit-test coverage. Almost everything is [Gui]--request->[Middleware]--request-->[Proxy]--request-->[Backend]->[Database].
In reality, [Middleware] and [Backend] probably should have been a single component, but devs wanted to do microservices, and be scalable, but they didn't really understand the bounded contexts of their services.
All of this leads us to a place, where unit-tests don't tell us much.
On the other hand, we managed to spawn [Middleware]->[Backend]->[Database], and we can run a useful integration tests-suite in ~2 minutes.
So, on one hand, if we desined this better, the good-old pyramid might be a working strategy. On the other hand, if I can get actual services running in minute, and test them end-to-end, I don't think I will bother with true unit-tests on my next projects. I.e. why mock the database, if I can spawn it seconds :-)