简体   繁体   中英

How to test and mock zend framework controllers with PHPUnit?

Im trying to unit test my controllers, but every tutorial I found on the internet says that I should use $this->dispatch("controller/action") to run the specific action I want to test. But doing it like that, I can't mock anything like data mappers, or other calls to other methods.

To solve this, I was trying to get an instance of the controller class, and then calling directly to the methods I wanted to test, but doing it like this, I get an error:

Zend_Exception: Setting request object manually is not allowed

Im not even sure this is the right approach, because I dont really know how I will test things doing it like this.

My test case: http://pastie.org/1812717

My ControllerTestCase: http://pastie.org/1812722

Any help would be appreciated. Thank you.

You have two solutions:

  1. Pseudo unit testing (more like acceptance testing) with Zend_Test_PHPUnit_ControllerTestCase
  2. Creating new instance of the Controller, passing all the required dependencies (dispatcher, request, response, plugin managers etc.)

Both of them actually require dispatching process. The first, dispatching the application, second, dispatching the controllers.

See the manual and sample tests from the full Zend Framework package.

Also, look at the controller source code, to see, how the dependencies are managed.

See also other SO posts about Dependency Injection to the Zend Framework controllers.

I would guess that Zend_Test_PHPUnit_ControllerTestCase is preventing you from being able to mock Requset and Response objects. I would bypass it and just extend PHPUnit_Framework_TestCase. As I mentioned in another question, I am currently mocking Controllers without any problems.

Here is an example test that runs fine:

http://pastie.org/1816705

AbstractRestController is simply a controller class that extends Zend_Controller_Action

How is your data mapper (or other objects) instantiated? Are you instantiating it directly in the controller or grabbing it from the bootstrap/registry? If using registry or bootstrap, then place the mock in the registry/bootstrap.

If you are directly instantiating in the controller, you will need to modify your controller. Maybe have a controller method to set the data mapper, and then have another method to grab the data mapper, and if one is not set, then instantiate it. That allows your tests to inject a mock.

I typically don't mock many classes when testing controllers - I want to test the entire app and its ability to render the page... It looks like you are testing no records in the database, so why not use Zend_Test_PHPUnit_Db to set up an empty table for that test, rather than mock the data mapper to return no data?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM