Reputation: 309
I want to test the add action of a controller method. I want to verify to result of a save action. So basically I want to send a post to the action and verify the result in my test by using a find after the request is finished. $this->testAction() doesn’t seem to be the right way to do this (see comments in the code below). How should this be done?
Controller code is something like:
Public function add() {
.....
if ($this->request->is('post') && isset($this->request->data['InvoiceEntry'])) {
....
$this->request->data = $this->__someMethod($this->request->data);
if ($this->Invoice->saveAssociated($this->request->data)) {
....
$this->redirect(array('action' => 'index'));
}
.....
}
Test code:
public function testAdd() {
$data = array('Invoice' => array(...), 'InvoiceEntry' => array(....));
// Method 1
$this->testAction('/invoices/add/', array(
'method' => 'post',
'data' => $data,
));
// Unable to do find after testAction because testAction basically is the test?
// Method 2:
$this->controller = $this->generate('Invoices');
$_SERVER['REQUEST_METHOD'] = 'POST';
$this->controller->requestAction('/invoices/add',array(
'data' => $data
));
// not working because requestAction() follows the redirect in the add method
}
Upvotes: 0
Views: 1661
Reputation: 34877
First of all, you should initialize your Model class in the test's setUp()
method:
public function setUp() {
parent::setUp();
$this->Invoice = ClassRegistry::init('Invoice');
}
After that you can just use that model as you otherwise would. So after you do:
$this->testAction('/invoices/add/', array(
'method' => 'post',
'data' => $data,
));
You should then be able to check if it was added, for example by doing:
/*
* Check if the last insert id is 13
* (NOTE: This actual number depends on how your fixture looks.)
*/
$this->assertEquals(13, $this->Invoice->getLastInsertID());
Or check some content, like:
// Find the latest invoice
$invoice = $this->Invoice->find('first', array(
'order' => array('id' => 'desc')
));
/*
* Verify the data matches your $data array
* e.g. if the customer_id of this invoice is 1
* (this depends on what is actually in $data)
*/
$this->assertEquals(1, $invoice['Invoice']['customer_id']);
Finally, don't forget to destruct the Model instance in your tearDown()
method:
public function tearDown() {
unset($this->Invoice);
parent::tearDown();
}
Upvotes: 1
Reputation: 498
You should be able to do anything after a testAction
. It's not the test itself, it just runs the code in the action.
What happens if you do a Model::find()
after your testAction
? Or even a debug('foo');exit;
? This should be executed.
By the way, in your controller you should use return
in front of a redirect. It's recommended by CakePHP because has you terminal is not a browser (I assume you test with the command line, not the webroot/test.php
, and if you do stop and use the terminal as testing via your browser can lead to incoherent tests because of cookies/sessions) and won't follow the redirect, therefor will execute the code that may be after the Controller::redirect()
, and you don't want that :)
Upvotes: 1