【问题标题】:CakePHP 2.4 mock a method in a modelCakePHP 2.4 模拟模型中的方法
【发布时间】:2013-11-15 16:33:44
【问题描述】:

我想测试一个模型,对于其中一个测试,我想模拟我正在测试的模型的一个方法。所以我不测试控制器,也不想替换整个模型,只是我测试的同一模型的一种方法。

原因是这个模型方法调用了一个文件上传处理程序。此功能已在其他地方进行了测试。

我现在做的是: 我测试模型“内容”。在那里我测试了它的方法'addTeaser',它调用了'sendTeaser'。 所以我想模拟 sendTeaser 并伪造方法 sendTeaser 的成功答案,同时测试 addTeaser。

看起来像这样:

    $model = $this->getMock('Content', array('sendTeaser'));
    $model->expects($this->any())
    ->method('sendTeaser')
    ->will($this->returnValue(array('ver' => ROOT.DS.APP_DIR.DS.'webroot/img/teaser/5/555_ver.jpg')));


    $data = array(
        'Content' => array(
            'objnbr' => '555',
            'name' => '',
             ...
            )
        )
    );
    $result = $model->addTeaser($data);
    $expected = true;
    $this->assertEquals($expected, $result);

当我让我的测试运行时,我收到一个错误,即方法“sendTeaser”中的模型未正确调用。嘿!它不应该被调用!我嘲笑了这个方法! .....还是不?

模拟该方法的正确语法是什么?

非常感谢一如既往的帮助!

灾难简

编辑: 这是我的模型的相关代码:

    App::uses('AppModel', 'Model');
    /**
    * Content Model
    *
    * @property Category $Category
    */
    class Content extends AppModel {

    public $dateipfad = '';
    public $fileName = '';
    public $errormessage = '';
    public $types = array(
        'sqr' => 'square - more or less squarish',
        'hor' => 'horizontal - clearly wider than high',
        'lnd' => 'landscape - low but very wide',
        'ver' => 'column - clearly higher than wide',
    );
    public $order = "Content.id DESC";
    public $actsAs = array('Containable');

    public $validateFile = array(
        'size' => 307200,
        'type' => array('jpeg', 'jpg'),
    );


    //The Associations below have been created with all possible keys, those that are not needed can be removed

    public $hasMany = array(
        'CategoriesContent' => array(
        'className' => 'CategoriesContent',
        ),
        'ContentsTag' => array(
        'className' => 'ContentsTag',
        ),
        'Description' => array(
        'className'  => 'Description',
        )
    );





    /**
    * Saves the teaser images of all formats.
    *
    * @param array $data
    *
    * @return Ambigous <Ambigous, string, boolean>
    */
    public function addTeaser($data)
    {
        $objnbr = $data['Content']['objnbr'];
        $type = $data['Content']['teaser-type'];

        if (!empty($data['Content']['teaser-img']['tmp_name'])) {
        $mFileNames = $this->sendTeaser($data, $objnbr, $type);
        }

        if (!is_array($mFileNames)) {
        $error = $mFileNames;
        //Something failed. Remove the image uploaded if any.
        $this->deleteMovedFile(WWW_ROOT.IMAGES_URL.$mFileNames);
        return $error;
        }
        return true;
    }



    /**
    * Define imagename and save the file under this name.
    *
    * Since we use Imagechache, we don't create a small version anymore.
    *
    * @param integer $objnbr
    * @param string $teasername
    *
    * @return multitype:Ambigous <string, boolean> |Ambigous <boolean, string>
    */
    public function sendTeaser($data, $objnbr, $type)
    {
        //$path = str_replace('htdocs','tmp',$_SERVER['DOCUMENT_ROOT']);
        $this->fileName = $this->getImageName($objnbr, $type);
        $oUH = $this->getUploadHandler($data['Content']['teaser-img']);
        debug($oUH);
        exit;
        $error = $oUH->handleFileUpload();
        if (empty($type))
        $type = 0;
        if ($error === 'none'){
        // Send to ImageChacheServer
        $oICC = $this->getImagecacheConnector();
        $sCacheUrl = $oICC->uploadFile($objnbr, $type, $this->fileName);
        debug($sCacheUrl);
        return array($type => $this->fileName);
        }
        return $error;
    }


    public function getUploadHandler($imgdata)
    {
        App::uses('UploadHandler', 'Lib');
        $oUH = new UploadHandler($this, $imgdata);
        return $oUH;
    }



}

将 getMock 更改为 getMockForModel 并没有改变输出。

【问题讨论】:

  • 试试CakeTestCase::getMockForModel()(它可能不会有什么不同,但无论如何你最好使用它),如果没有帮助,请出示你的型号代码。
  • 我添加了模型代码以及与上述问题相关的方法。
  • 您忘记包含类声明和可能的前面App:uses() 调用。您还可以尝试将问题缩小到一个简单的两个方法示例类,并尽可能减少依赖关系(即,在addTeaser()sendTeaser() 中使用虚拟代码,删除验证、关联等,只要问题仍然存在)?哦,错误是否显示堆栈跟踪?
  • 打开 php 标签让类声明消失。现在它是可见的。发生的错误是 UploadHandler $oUH 未正确加载。但我不在乎,因为不应该调用使用 Uploadhandler 的方法。但是我将类中的代码简化为两个重要的方法并删除所有,它们只被应该被模拟的方法调用,因此不被调用。
  • 真正的问题是:为什么我的测试调用了 sendTeaser?或者我该如何设置我的 addTeaser 测试,以便不调用 sendTeaser。谢谢!灾厄简

标签: unit-testing cakephp testing mocking cakephp-2.4


【解决方案1】:

我想强调@ndm 使用Cake test helper class CakeTestCase::getMockForModel() 的答案

$theModel = CakeTestCase::getMockForModel('Modelname', ['theMethodToMock']);
$theModel->expects($this->once())
         ->method('theMethodToMock')
         ->will($this->returnValue('valueToReturn'));

【讨论】:

    【解决方案2】:

    $this->getMock 不是模拟的方式。你应该使用 $this->generate

    我会推荐你​​读一本关于 CakePHP 非测试的书,像这样:https://leanpub.com/cakephpunittesting

    【讨论】:

    • 他说他想模拟一个模型,而不是一个控制器,所以合适的辅助方法是CakeTestCase::getMockForModel(),另外,如果你知道你在做什么,那么直接使用PHPUnit_Framework_TestCase::getMock()非常很有可能。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-19
    • 2020-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多