While creating a phpunit test against a form for Symfony 2, I encountered an interesting problem that made little sense to me at first (for reference, I was following an example for unit testing form types from the Symfony 2 website). The problem was that the data being submitted appeared to not be mapped correctly, which caused the unit test to fail unexpectedly. Why is that?
So here’s the gist of my unit test:
public function testSubmitData() { $data = array( 'name' => 'test123', 'region' => 'x' ); $type = new RealmRegionType(); $form = $this->factory->create($type); $model = new RealmRegion(); $model->setName('test123'); $model->setRegion('blorf'); $form->submit($data); $this->assertTrue($form->isSynchronized()); $this->assertEquals($model, $form->getData()); }
The failure was occurring on the last assert. At first, you would expect the assert to fail since ‘blorf’ != ‘x’. However, I tried changing ‘blorf’ to ‘x’ but the test continued to fail. More surprisingly, in examining both the data from $form->getData() and comparing it to the $model, I noticed that the ‘region’ data member wasn’t being set. So what was going on?
The thing about the ‘region’ data member that you cannot see in the example above, is that it has some constraints defined in the form itself. Here is what the code from the form (RealmRegionType.php) looks like which causes the rejection in the ‘region’ field:
public function buildForm(FormBuilderInterface $b, array $options) { $b->add('name', 'text') ->add('region', 'choice', array( 'choices' => array('us' => 'US', 'eu' => 'EU', 'cn' => 'CN', 'kr' => 'KR'), 'required' => true, 'expanded' => true )) ->add('save', 'submit'); }
As you can see here, region is expecting limited types of string values and is rejecting anything else, which causes the ‘region’ data member to show up as null (if you use say print_r). My actual model will accept a 2 character string limit but the form itself adds a step to protect my model from bad data. If I set the ‘region’ in the $data hash to ‘eu’ and set the model’s ‘region’ to ‘eu’ my test will succeed.
One other note here in relation to the article linked is that the article’s model is a Propel model. So there’s a few lines (like ->fromArray()) which does not appear to have a corresponding method for Doctrine. In that sense, your unit test using a Doctrine model might differ slightly if you go by the article’s method.
Leave a Reply
You must be logged in to post a comment.