cakephp测试控制器:数据库mock没有返回任何东西

时间:2016-07-15 07:05:18

标签: cakephp phpunit

我是CakePHP和PHPUnit的新手,我想测试一个控制器。到目前为止,我喜欢测试这种方法:

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));
}

现在我想测试是否在我的模型Designitem上调用了getItemsWithFurnitures。为了测试这个,我实现了这个测试:

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);
}

编辑:我的Designitems Fixture包含一个存根条目。它看起来像这样:

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'
    ),
);

}

当我运行测试时,我得到一个错误,getItemsWithFurnitures返回null:

Test result

谁能告诉我自己做错了什么?谢谢!

1 个答案:

答案 0 :(得分:1)

我找到了问题的解决方案。我的问题是getItemsWithFurnitures没有返回null,但测试方法getAlternatives没有返回任何值( - > null)。所以我必须检查设置值$this->set(...);是否与预期的数组相同。要实现这一点,我必须通过传递testAction(...)来更改array('return' => 'contents')的返回方法。然后它将返回生成的内容而不是方法返回值。工作测试如下:

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);
}

因为我将这些项目添加到另一个阵列中并且替代方案'在将其设置为视图时,我必须将预期的数组放在这个' alternative' -array中。我还必须替换所有空格,因为使用的json编码方法是不同的。为了比较它们,它们必须完全相同,所以我删除了空格和测试通道。

我希望有人可以使用此信息。