Issue
I'm new to CakePHP and PHPUnit and I want to test one of my controllers. So far I have this method I like to test:
public function getAlternatives($id = null){
// ID parameter given or is NaN?
if (!$id || !is_numeric($id)) {
throw new BadRequestException();
}
// Error if object not found
if (!$this->Designitem->exists($id)) {
throw new NotFoundException();
}
$alternatives = $this->Designitem->getItemsWithFunritures($id);
$this->set(array(
'alternatives' => $alternatives,
'_serialize' => array('alternatives'),
'_jsonp' => true));
}
Now I want to test whether the getItemsWithFurnitures is called on my model Designitem. To test this I implemented this test:
public function testGetAlternativesWithValidID() {
$id = 1;
$url = array('controller' => 'Designitems', 'action' => 'getAlternatives', $id . '.json');
$expected = array(
'Designitem' =>
array(
'id' => 1,
'design_id' => 1,
'furniture_id' => 1,
'template_id' => 1,
),
);
$designitems = $this->generate('Designitems', array(
'methods' => array(
'getAlternatives',
),
'models' => array(
'Designitem' => array('getItemsWithFunritures'),
),
));
$designitems->Designitem
->expects($this->once())
->method('getItemsWithFunritures')
->will($this->returnValue($expected));
$result = $this->testAction($url);
$this->assertEquals(json_encode($expected), $result);
}
EDIT: My Designitems Fixture contains one stubbed entry. It looks like this:
class DesignitemFixture extends CakeTestFixture {
public $fields = array(
'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false, 'key' => 'primary'),
'design_id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false),
'furniture_id' => array('type' => 'integer', 'null' => false, 'default' => null, 'unsigned' => false),
'template_id' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false),
'templateitem_id' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false),
'amount' => array('type' => 'integer', 'null' => false, 'default' => null, 'length' => 5, 'unsigned' => false),
'feedback' => array('type' => 'string', 'null' => true, 'default' => null, 'length' => 20, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'),
'clicks' => array('type' => 'integer', 'null' => true, 'default' => '0', 'unsigned' => false),
'ilike' => array('type' => 'boolean', 'null' => false, 'default' => null),
'dislike' => array('type' => 'boolean', 'null' => false, 'default' => null),
'dislike_reason' => array('type' => 'string', 'null' => false, 'default' => null, 'length' => 100, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'),
'dislike_comment' => array('type' => 'string', 'null' => false, 'default' => null, 'length' => 2000, 'collate' => 'utf8_general_ci', 'charset' => 'utf8'),
'parent_id' => array('type' => 'integer', 'null' => true, 'default' => null, 'unsigned' => false),
'has_alternatives' => array('type' => 'boolean', 'null' => true, 'default' => null),
'is_selected' => array('type' => 'boolean', 'null' => true, 'default' => null),
'is_recommendation' => array('type' => 'boolean', 'null' => true, 'default' => null),
'deleted' => array('type' => 'integer', 'null' => false, 'default' => null, 'length' => 4, 'unsigned' => false),
'deleted_date' => array('type' => 'datetime', 'null' => true, 'default' => null),
'created' => array('type' => 'datetime', 'null' => true, 'default' => null),
'modified' => array('type' => 'datetime', 'null' => true, 'default' => null),
'indexes' => array(
'PRIMARY' => array('column' => 'id', 'unique' => 1)
),
'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB')
);
public $records = array(
array(
'id' => 1,
'design_id' => 1,
'furniture_id' => 1,
'template_id' => 1,
'templateitem_id' => 1,
'amount' => 1,
'feedback' => 'Lorem ipsum dolor ',
'clicks' => 1,
'ilike' => 1,
'dislike' => 1,
'dislike_reason' => 'Lorem ipsum dolor sit amet',
'dislike_comment' => 'Lorem ipsum dolor sit amet',
'parent_id' => 1,
'has_alternatives' => 1,
'is_selected' => 1,
'is_recommendation' => 1,
'deleted' => 0,
'deleted_date' => '2016-07-14 12:05:39',
'created' => '2016-07-14 12:05:39',
'modified' => '2016-07-14 12:05:39'
),
);
}
When I run the test, I get an error that the getItemsWithFurnitures returned null:
Can anyone tell me what I'm doing wrong? Thank you!
Solution
I found a solution to the problem. My problem was that not the getItemsWithFurnitures returned null but the tested method getAlternatives isn't returning any value (-> null). So I have to check if the set value $this->set(...);
is the same as the expected array. To achieve this I have to change the return method of the testAction(...)
by passing array('return' => 'contents')
. It will then return the produced content instead of the methods return value. The working test looks like this:
public function testGetAlternativesWithValidID() {
$id = 1;
$url = array('controller' => 'Designitems', 'action' => 'getAlternatives', $id . '.json');
$this->_generateMockWithAuthUserId('Designitems', 1);
$expected = array(
'Designitem' =>
array(
'id' => 1,
'design_id' => 1,
'furniture_id' => 1,
'template_id' => 1,
),
);
$data = $this->getMockForModel('Designitem', array('getItemsWithFunritures'));
$data->expects($this->once())
->method('getItemsWithFunritures')
->will($this->returnValue($expected));
$result = $this->testAction($url, array('return' => 'contents'));
// Delete all whitespaces from the result.
$result = preg_replace('/\s+/', '', $result);
// Add the surrounding alternatives array to the expected and convert to json-format.
$expected = json_encode(array('alternatives' => $expected));
$this->assertEquals($expected, $result);
}
Because I add these items into another array 'alternatives' while setting it to the view, I have to place the expected array in this 'alternatives'-array. I also had to replace all whitespaces because the json encoding methods used are different. In order to compare them they have to be exactly the same so I removed the whitespaces and the test passes.
I hope someone can use this info.
Answered By - lukas
0 Comments:
Post a Comment
Note: Only a member of this blog may post a comment.