Вопрос: Как добиться независимости в тестах (phpunit)?

Лучший ответ: Не стоит смешивать модульные тесты и интеграционные (или функциональные). Цель модульных тестов проверить работу одного модуля (класса, например). В этом случае все его зависимости мокаются. Целью интеграционных тестов является проверка взаимодействия цепочки модулей (сервисов, с БД и т.п.) друг с другом.
То что вы написали похоже на интеграционные тесты. Очевидно, что такие тесты будут падать, если что-то не работает в любом месте всей тестируемой цепочки модулей. И это не связано с изоляцией тестов друг от друга.
То есть правильно было бы сформулировать вопрос таким образом: "какой процент покрытия модульными тестами будет достаточным для моего кода?" Обычно останавливаются где-то на 70-80%
Также очевидно, что 100% работающих модульных тестов не гарантирует работу интеграционных тестов или функциональных. Поэтому необходимо писать и те и другие.
Я бы не стал фанатично закрывать все методы классов тестами, а только те, в которых имеется высокая цикломатическая сложность, либо которые скорее всего будут меняться. Короче, нет большого смысла в тестировании примитивных/стабильных участков кода.

Худший ответ: я в основном делаю ui тесты и у меня некоторые тесты связаны друг с другом. конечное состояние первого теста является начальным сосотоянием следующего. Например первый тест "зайти в формуляр"  а следующий за ним "ввести данные в первую строку" а затем тест "ввести данные во вторую строку" а потом "нажать на отправку данных" а потом "тест сообщения об отправке". Естественно если первый тест завалится, завалятся и все после него, хотя реальная проблема только одна. Единственный серьезный недостаток такого подхода, это возможное перекрытие ошибок. Т.е. в билде может сломаться заход в формуляр, и отображение сообщения об отправке. Вторая проблема будет перекрыта первой. 
Но меня устраивает такой подход по следующим соображениям. 
- Если что-то сломалось в приложение надо в первую очередь чинить приложение, а не писать тонны дополнительного тестировочного кода. 
- Тестировочный код тоже код, чем его больше тем больше вероятность сделать ошибку в нем. 
- Лучше потратить время на увеличение покрытие пользовательских сценариев, чем на создание красивой и каноничной автоматизации. 
- Зависимые тесты выполняются быстрее, (а у нас время тестирования билда во всех вариациях уже перевалило за 16 часов)
- Чинить по одной ошибке за раз - хорошо, пытаясь починить сразу несколько можно сломать что-то еще. 
Для того чтобы такой подход работал более менее чисто, я например стараюсь сдвигать все проверки в конец теста, уменьшая таким образом вероятность того что вылетевшее исключение не доведет приложение до нужного состояния для последующего теста. 
Но это все не по вашему вопросу. По вашему вопросу - да, писать тонны моков (не нужно). У меня например есть тесты которые проверяют как данные от железа передаются в api графического клиента. при проверке фунцкионала графического клиента, я опираюсь на корректную работу api графического клиента, поскольку им пользуюсь. Так же я опираюсь на корректную работу виджетов. И если какие-то условия не будут работать многие ui тесты посыплются. Мы найдем причину и устраним ее.  Чтобы в таком случае падал только один тест, который специально сделан для нахождения этой ошибки, вам придется отвязать тестируемую компоненту от всех внешних зависимостей. Теоретически написав столько же кода сколько в самом приложении. Вы готовы к этому?
P.S.: стоит добавить: наш тест-фреймворк выполняет тесты в алфавитном порядке и не поддерживает параллельное выполнение в принципе.