Lưu ý: Đây là Symfony < 2,6 nhưng tôi tin rằng các vấn đề tổng thể cũng áp dụng không phân biệt phiên bảnLàm thế nào để đạt được sự cô lập thử nghiệm với các biểu mẫu Symfony và các máy biến dữ liệu?
Để bắt đầu, hãy xem xét loại hình thức này được thiết kế để đại diện cho một-or-nhiều thực thể như một lĩnh vực tiềm ẩn (namespace thứ bỏ qua cho ngắn gọn)
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';
}
}
này hoạt động, đó là đơn giản, và cho hầu hết các phần trông giống như giống như tất cả các ví dụ mà bạn nhìn thấy để thêm biến dữ liệu đến một kiểu mẫu. Cho đến khi bạn nhận được để kiểm tra đơn vị. Xem vấn đề? Các máy biến áp không thể bị chế nhạo. "Nhưng chờ đã!" bạn nói, "Bài kiểm tra đơn vị cho các biểu mẫu của Symfony là các bài kiểm tra tích hợp, chúng phải đảm bảo rằng các biến không thành công. Thậm chí nói như vậy là in the documentation!"
Kiểm tra này kiểm tra xem không có biến số dữ liệu nào của bạn được sử dụng theo biểu mẫu không thành công. Phương thức isSynchronized() chỉ được đặt thành false nếu dữ liệu biến áp ném một ngoại lệ
Ok, vậy thì bạn sống với thực tế bạn không thể cách ly máy biến áp. Không phải vấn đề lớn?
Bây giờ xem xét những gì sẽ xảy ra khi đơn vị thử nghiệm một hình thức mà có một trường thuộc loại này (giả sử rằng HiddenEntityType
đã được định nghĩa & gắn thẻ trong container dịch vụ)
class SomeOtherFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('field', 'hidden_entity', array(
'class' => 'AppBundle:EntityName',
'multiple' => true,
));
}
/* ... */
}
Bây giờ đi vào vấn đề. Kiểm tra đơn vị cho SomeOtherFormType
hiện cần triển khai getExtensions()
để loại hidden_entity
hoạt động. Vậy nó trông như thế nào?
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()
)
);
}
Xem nơi nhận xét đó nằm ở chính giữa? Vâng, do đó, để điều này hoạt động chính xác, tất cả các mocks và kỳ vọng trong lớp kiểm tra đơn vị cho HiddenEntityType
giờ đây cần được sao chép ở đây một cách hiệu quả. Tôi không đồng ý với điều này, vì vậy lựa chọn của tôi là gì?
Tiêm biến áp là một trong những lựa chọn
này sẽ rất đơn giản và có thể làm cho chế giễu đơn giản hơn, nhưng cuối cùng chỉ đá lon xuống đường. Bởi vì trong trường hợp này,
new EntityToPrimaryKeyTransformer()
sẽ chỉ chuyển từ một loại loại biểu mẫu này sang lớp loại khác. Chưa kể rằng tôi cảm thấy các loại biểu mẫu nên ẩn nội dung phức tạp của chúng khỏi phần còn lại của hệ thống. Tùy chọn này có nghĩa là đẩy sự phức tạp đó ra ngoài ranh giới của loại biểu mẫu.Tiêm một nhà máy biến áp các loại thành các loại hình thức
Đây là một cách tiếp cận điển hình hơn để loại bỏ "newables" từ bên trong một phương pháp, nhưng tôi không thể rung cảm giác rằng điều này đang được thực hiện chỉ để làm cho mã có thể kiểm tra và không thực sự làm cho mã tốt hơn. Nhưng nếu điều đó được thực hiện, nó sẽ trông giống như thế này
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 */ }
Điều này cảm thấy ok cho đến khi tôi xem xét nhà máy sẽ trông như thế nào. Nó sẽ cần quản lý thực thể được tiêm, cho người mới bắt đầu. Nhưng những gì sau đó?Nếu tôi nhìn xa hơn xuống con đường, nhà máy được cho là chung chung này có thể cần tất cả các loại phụ thuộc để tạo ra các máy biến áp dữ liệu thuộc các loại khác nhau. Đó rõ ràng không phải là một quyết định thiết kế lâu dài tốt. Vậy thì sao? Đánh dấu lại tên này là
EntityManagerAwareDataTransformerFactory
? Nó bắt đầu cảm thấy lộn xộn ở đây.Stuff Tôi không nghĩ đến việc ...
Suy nghĩ? Kinh nghiệm? Lời khuyên vững chắc?
Cảm ơn bạn đã trả lời và thậm chí nhiều hơn thế, cảm ơn bạn đã làm rõ nguồn gốc của đề xuất của bạn. Nó luôn luôn tốt đẹp để thêm sách mới vào danh sách đọc. –