6

我刚刚开始在 CakePHP 中进行单元测试(耶!)并遇到了以下挑战。希望有人可以帮助我:-)

情况

我的模型在本地保存后使用 Behavior 将更改发送到 API。我想伪造测试期间对 API 的所有调用(这些调用将单独测试)以节省 API 服务器上的负载,更重要的是,实际上不保存更改 :-)

我正在使用 CakePHP 2.4.1。

我试过的

  • 阅读文档。该手册显示了如何为组件和助手执行此操作,但不为行为显示。
  • 谷歌。我发现了什么:

文章中的代码如下:

$provider = $this->getMock('OurProvider', array('getInfo'));
$provider->expects($this->any())
    ->method('getInfo')
    ->will($this->returnValue('200'));

这可能是错误的方向,但我认为这可能是一个好的开始。

我想要的是

有效:一段代码,用于演示如何在 CakePHP 模型中模拟行为以进行单元测试。

也许这个问题会导致添加 CakePHP 手册作为额外的奖励,因为我觉得它在那里丢失了。

提前感谢您的努力!

更新 (2013-11-07)

我发现了这个相关的问题,它应该(部分)回答这个问题。无需模拟 API,我可以创建模型将使用的行为测试。

我试图弄清楚 BehaviorTest 应该是什么样子。

4

1 回答 1

10

使用类注册表

与许多类一样,使用类名作为键将行为添加到类注册表中,并且对于从类注册表加载的同一对象的后续请求。因此,模拟一个行为的方法就是在使用它之前把它放在类注册表中。

完整示例:

<?php
App::uses('AppModel', 'Model');

class Example extends AppModel {

}
class TestBehavior extends ModelBehavior {

    public function foo() {
        throw new \Exception('Real method called');
    }
}

class BehaviorExampleTest extends CakeTestCase {

    /**
     * testNormalBehavior
     *
     * @expectedException Exception
     * @expectedExceptionMessage Real method called
     * @return void
     */
    public function testNormalBehavior() {
        $model = ClassRegistry::init('Example');
        $model->Behaviors->attach('Test');

        $this->assertInstanceOf('TestBehavior', $model->Behaviors->Test);
        $this->assertSame('TestBehavior', get_class($model->Behaviors->Test));
        $this->assertSame(['foo' => ['Test', 'foo']], $model->Behaviors->methods());

        $model->foo();
    }

    public function testMockedBehavior() {
        $mockedBehavior = $this->getMock('TestBehavior', ['foo', 'bar']);
        ClassRegistry::addObject('TestBehavior', $mockedBehavior);

        $model = ClassRegistry::init('Example');
        $model->Behaviors->attach('Test');

        $this->assertInstanceOf('TestBehavior', $model->Behaviors->Test);
        $this->assertNotSame('TestBehavior', get_class($model->Behaviors->Test));

        $expected = [
            'foo' => ['Test', 'foo'],
            'bar' => ['Test', 'bar'],
            'expects' => ['Test', 'expects'], // noise, due to being a mock
            'staticExpects' => ['Test', 'staticExpects'], // noise, due to being a mock
        ];
        $this->assertSame($expected, $model->Behaviors->methods());

        $model->foo(); // no exception thrown

        $mockedBehavior
            ->expects($this->once())
            ->method('bar')
            ->will($this->returnValue('something special'));

        $return = $model->bar();
        $this->assertSame('something special', $return);
    }
}
于 2013-11-07T11:42:21.187 回答