Desculpem o necro deste post, mas sinto-me compelido a considerar algumas coisas que parecem não ter sido tocadas.
Em primeiro lugar - quando nos encontramos precisando de acesso a membros particulares de uma classe durante o teste de unidade, geralmente é uma bandeira vermelha grande e ridícula que brincamos em nossa abordagem estratégica ou tática e violamos inadvertidamente o diretor de responsabilidade única pressionando comportamento onde não pertence. Sentir a necessidade de acessar métodos que nada mais são do que uma sub-rotina isolada de um procedimento de construção é uma das ocorrências mais comuns; no entanto, é como se seu chefe esperasse que você aparecesse para o trabalho pronto para ir e também tenha alguma necessidade perversa de saber por que rotina matinal você passou para entrar nesse estado ...
O outro exemplo mais comum desse acontecimento é quando você tenta testar a proverbial "classe divina". É um tipo especial de problema por si só, mas sofre do mesmo problema básico por precisar conhecer detalhes íntimos de um procedimento - mas isso está saindo do tópico.
Neste exemplo específico, atribuímos efetivamente a responsabilidade de inicializar totalmente o objeto Bar ao construtor da classe FooBar. Na programação orientada a objetos, um dos principais inquilinos é que o construtor é "sagrado" e deve ser protegido contra dados inválidos que invalidariam seu próprio estado interno e o deixariam preparado para falhar em outro lugar a jusante (no que poderia ser muito profundo). pipeline.)
Falhamos em fazer isso aqui, permitindo que o objeto FooBar aceite uma barra que não está pronta no momento em que o FooBar é construído e compensamos com uma espécie de "invasão" do objeto FooBar para resolver os problemas por conta própria mãos
Isso é o resultado de uma falha em aderir a outro conteúdo da programação orientada a objetos (no caso de Bar), que significa que o estado de um objeto deve estar totalmente inicializado e pronto para lidar com as chamadas recebidas de seus membros públicos imediatamente após a criação. Agora, isso não significa imediatamente após o construtor ser chamado em todas as instâncias. Quando você tem um objeto que possui muitos cenários de construção complexos, é melhor expor os setters a seus membros opcionais a um objeto implementado de acordo com um padrão de design de criação (Factory, Builder, etc ...) os últimos casos,
No seu exemplo, a propriedade "status" da barra não parece estar em um estado válido no qual um FooBar possa aceitá-la - portanto, a FooBar faz algo para corrigir esse problema.
O segundo problema que estou vendo é que parece que você está tentando testar seu código em vez de praticar o desenvolvimento orientado a testes. Esta é definitivamente a minha opinião neste momento; mas, esse tipo de teste é realmente um anti-padrão. O que você acaba fazendo é cair na armadilha de perceber que possui problemas essenciais de design que impedem que seu código seja testável após o fato, em vez de gravar os testes necessários e, posteriormente, programar os testes. De qualquer forma, você enfrenta o problema, ainda deve ter o mesmo número de testes e linhas de código se realmente tiver conseguido uma implementação do SOLID. Então - por que tentar fazer uma engenharia reversa em código testável quando você pode apenas resolver o problema no início de seus esforços de desenvolvimento?
Se você tivesse feito isso, teria percebido muito antes que teria que escrever um código bastante nojento para testar seu design e teria tido a oportunidade desde o início de realinhar sua abordagem, mudando o comportamento para implementações que são facilmente testáveis.