注:これはsymfonyの< 2.6であるが、私は隠しフィールドとして、一または-複数のエンティティを表現するために設計されたこのフォームの種類を考慮し、同じ全体的な問題を開始するにはバージョンに関係なくSymfonyフォームとデータトランスフォーマーでテスト分離を達成するには?
の適用と信じて(簡潔にするため省略した名前空間のもの)
class HiddenEntityType extends AbstractType
{
/**
* @var EntityManager
*/
protected $em;
public function __construct(EntityManager $em)
{
$this->em = $em;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
if ($options['multiple']) {
$builder->addViewTransformer(
new EntitiesToPrimaryKeysTransformer(
$this->em->getRepository($options['class']),
$options['get_pk_callback'],
$options['identifier']
)
);
} else {
$builder->addViewTransformer(
new EntityToPrimaryKeyTransformer(
$this->em->getRepository($options['class']),
$options['get_pk_callback']
)
);
}
}
/**
* See class docblock for description of options
*
* {@inheritdoc}
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'get_pk_callback' => function($entity) {
return $entity->getId();
},
'multiple' => false,
'identifier' => 'id',
'data_class' => null,
));
$resolver->setRequired(array('class'));
}
public function getName()
{
return 'hidden_entity';
}
/**
* {@inheritdoc}
*/
public function getParent()
{
return 'hidden';
}
}
これは動作しますが、それは簡単だし、ほとんどの部分は、フォームタイプにデータ変圧器を追加するための参照すべての例のようにのように見えます。あなたが単体テストになるまで。問題を参照してください?変圧器を嘲笑することはできません。 "ちょっと待って!" 「Symfonyフォームの単体テストは統合テストであり、トランスフォーマーが失敗しないことを確認することになっています。でもそうですin the documentation!」
このテストでは、 というフォームで使用されているデータトランスフォーマがどれも故障していないことを確認します。データ 変圧器は例外
[OK]をスローした場合IsSynchronizedのトピック()メソッドは、だけなので、あなたは、あなたが変圧器を隔離することができないという事実と一緒に暮らす、falseに設定されています。大きな問題ではない?
今、このタイプのフィールドを有するフォームをテストユニット(HiddenEntityType
サービスコンテナにタグ付けされた&を定義されていると仮定)
class SomeOtherFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('field', 'hidden_entity', array(
'class' => 'AppBundle:EntityName',
'multiple' => true,
));
}
/* ... */
}
今問題に入ったときに何が起こるかを考えます。 SomeOtherFormType
のユニットテストは、hidden_entity
タイプが機能するために今やgetExtensions()
を実装する必要があります。だから、どうやって見えるの?
protected function getExtensions()
{
$mockEntityManager = $this
->getMockBuilder('Doctrine\ORM\EntityManager')
->disableOriginalConstructor()
->getMock();
/* Expectations go here */
return array(
new PreloadedExtension(
array('hidden_entity' => new HiddenEntityType($mockEntityManager)),
array()
)
);
}
コメントはどこに表示されていますか。うん、これが正しく動作するためには、HiddenEntityType
の単体テスト・クラスにあるすべてのモックと期待は、ここでは事実上ここに複製する必要があります。私はこれでOKではないので、私の選択肢は何ですか?
- はオプション
これは非常に簡単だろうと単純にモックなるだろうの一つとして、変圧器を注入するが、最終的にちょうど道缶けり。このシナリオでは、
new EntityToPrimaryKeyTransformer()
は1つのフォームタイプクラスから別のフォームタイプクラスに移動するだけなので、私はフォームの種類がなら、はシステムの残りの部分から隠蔽しなければならないと感じていることは言うまでもありません。このオプションは、その複雑さをフォームタイプの境界の外に押し出すことを意味します。 これはメソッド内から「newables」を除去することに、より一般的なアプローチですが、私はこれがちょうどに行われているという感覚を振り払うことができないフォームタイプに
を一種の変圧器工場を注入しますコードをテスト可能にし、実際にコードを改善していない。しかし、それが完了した場合、このようなものになります。
class HiddenEntityType extends AbstractType { /** * @var DataTransformerFactory */ protected $transformerFactory; public function __construct(DataTransformerFactory $transformerFactory) { $this->transformerFactory = $transformerFactory; } public function buildForm(FormBuilderInterface $builder, array $options) { $builder->addViewTransformer( $this->transformerFactory->createTransfomerForType($this, $options); ); } /* Rest of type unchanged */ }
これは工場が実際にどのように見えるかを検討するまでわかります。初心者には、エンティティマネージャを注入する必要があります。しかし、それは何ですか?道路をさらに見下ろすと、おそらくジェネリックな工場では、さまざまな種類のデータトランスを作成するためにあらゆる種類の依存関係が必要になる可能性があります。それは明らかに良い長期的な設計決定ではありません。だから何?
EntityManagerAwareDataTransformerFactory
とラベルを付け直しますか?それはここで乱雑に感じ始めている。スタッフ私は...の
思考を考えていませんよ?経験?確かなアドバイス?
さらに、そう返事してくれてありがとうとは、あなたの勧告の明確なソースを作るためにあなたに感謝。読書リストに新しい本を追加することは常にいいです。 –