Извините за некро в этом посте, но я чувствую себя обязанным взвесить пару вещей, которые, кажется, не были затронуты.
Прежде всего - когда во время модульного тестирования нам нужен доступ к закрытым членам класса, это, как правило, большой, толстый красный флаг, который мы обманываем в нашем стратегическом или тактическом подходе и непреднамеренно нарушаем принцип единственной ответственности, подталкивая поведение там, где оно не принадлежит. Чувство необходимости доступа к методам, которые на самом деле являются не чем иным, как изолированной подпрограммой процедуры построения, является одним из наиболее распространенных случаев этого; тем не менее, это похоже на то, что ваш начальник ожидает, что вы явитесь на работу, готовый к работе, а также имеет некоторую извращенную потребность знать, через какую утреннюю рутину вы прошли, чтобы привести вас в это состояние ...
Другой наиболее распространенный случай этого происходит, когда вы пытаетесь проверить общеизвестный «класс бога». Это особая проблема сама по себе, но она страдает от той же самой основной проблемы, связанной с необходимостью знать интимные детали процедуры - но это выходит за рамки темы.
В этом конкретном примере мы фактически возложили ответственность за полную инициализацию объекта Bar конструктору класса FooBar. В объектно-ориентированном программировании одним из основных принципов является то, что конструктор является «священным» и должен быть защищен от недопустимых данных, которые могут сделать недействительным его собственное внутреннее состояние и оставить его готовым к сбою где-то еще вниз по течению (в том, что может быть очень глубоким). трубопровод.)
Мы не смогли сделать это здесь, позволив объекту FooBar принять Bar, который не был готов в момент создания FooBar, и компенсировали своего рода «взломом» объекта FooBar, чтобы все стало по-своему. Руки.
Это является результатом отказа придерживаться другого принципа объектно-ориентированного программирования (в случае Bar), который заключается в том, что состояние объекта должно быть полностью инициализировано и готово обрабатывать любые входящие вызовы его «открытых членов» сразу после создания. Теперь это не означает, что сразу после вызова конструктора во всех случаях. Когда у вас есть объект, который имеет много сложных сценариев построения, тогда лучше выставить сеттеры для его необязательных членов для объекта, который реализован в соответствии с шаблоном создания проекта (Factory, Builder и т. Д.) В любом из последние случаи,
В вашем примере свойство Bar «status», по-видимому, не находится в допустимом состоянии, в котором FooBar может его принять - поэтому FooBar что-то с ним делает, чтобы исправить эту проблему.
Вторая проблема, которую я вижу, заключается в том, что, похоже, вы пытаетесь протестировать свой код, а не практиковаться в разработке через тестирование. Это определенно мое собственное мнение на данный момент; но этот тип тестирования действительно является анти-паттерном. В конечном итоге вы попадаете в ловушку осознания того, что у вас есть основные проблемы проектирования, которые мешают тестированию вашего кода после факта, а не пишут необходимые вам тесты и впоследствии программируют для тестов. В любом случае, если вы решите проблему, вы все равно должны получить такое же количество тестов и строк кода, если бы вы действительно достигли реализации SOLID. Итак - зачем пытаться перепроектировать свой путь в тестируемый код, если вы можете просто решить этот вопрос в начале ваших усилий по разработке?
Если бы вы сделали это, то вы бы поняли гораздо раньше, что вам придется написать какой-то довольно странный код, чтобы протестировать ваш дизайн, и у вас была бы возможность на раннем этапе перестроить ваш подход, переключив поведение на реализации, которые легко проверяемы