Pregunta

I am new to the Zend Framework and PHPUnit. I am transforming a legacy application to a MVC architecture and am trying to write unit tests. I am somewhat familiar with unit testing concepts but am stuck with stubbing and mocking in general. For instance consider the following

In a controller action I am trying to test I pass in a member ID. I then initialize a member object using the ID. Then I call a number of methods associated with the member object and assign the return values to the view objects.

class A extends Zend_Controller_Action {
    public function viewAction() {
        $member = new Member($this->getRequest()-> getParam('id'));

        //perform various calls on the member object 

        $gender = $member->getGender();
        ...

        //assign the return values to the view object

        $this->view->assign('gender',$gender);   
        ...

     }
}

How do I mock the $member variable in my tests so that I can customize the methods return values?

If my understanding here is incorrect I would greatly appreciate some guidance.

Thank you!

¿Fue útil?

Solución

If I understand you correctly, you're writing a test for this action. In that case it's impossible to mock $member since the new instance is created inside the method. That's why we're all striving to float as many of our new statements as far up in the object graph as possible (DI).

Generally there is the special PHPunit testcase Zend_Test_PHPUnit to test your controllers.

But it is, as a matter of fact, very hard or even impossible to test ZF controllers correctly (meaning with full isolation). You'd be better of to test the rest of your app, your general library, etc.

In other words, in the ZF1 logic, the controller is the central wiring place (after the bootstrap), where a lot of new statements are traditionally used. Obviously that leads to non-testability because every instance which is created instead of injected, is unmockable.

As @vascowhite pointed out, it is also generally good to strive for lean controllers. This means, move as much logic as possible to your model layer. This will lead to less redundance (DRY) and better testability at the same time.

But pay attention not to bloat your models either. At one point you will probably want to factor some code out into additional components.

An additional problem is that you can't mock the Front Controller either since it's a singleton. So you really don't have many options to test such an action. The only option would be to inject the member instance or get it from the registry (not a good idea either).

So, given all that it is clear that you can't reach full isolation for your action tests. But

ZF2 will be much easier to test, though.

Otros consejos

You'd better start with covering controllers with functional tests. In this case you can bypass this mocking problem and get better coverage of test. Controllers are always hard to be covered with unit tests, because they are strongly coupled.

To write functional tests with ZF consider using Codeception: http://codeception.com/01-27-2012/bdd-with-zend-framework.html

Also, there are some examples, how a unit tests for controller can be made. But, sincerly, I recommend unit-testing controllers after functional tests for them are made.

http://codeception.com/docs/06-UnitTestsAndBDD#TestingController

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top