PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Tuesday, January 25, 2022

[FIXED] cakephp testing controller: database mock doesn't return anything

 January 25, 2022     cakephp, phpunit     No comments   

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:

Test result

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
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home
View mobile version

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing