Php 单元测试Zend Controller并模拟一些已执行的操作

Php 单元测试Zend Controller并模拟一些已执行的操作,php,zend-framework,mocking,phpunit,Php,Zend Framework,Mocking,Phpunit,我正在为我的控制器编写一些单元测试(phpunit3.6),希望验证操作是否正确等等。。他们被解雇了。这很容易。但是,一些控制器还通过不需要的模型执行某些操作,例如将记录插入数据库 我知道我需要模仿这些,但不清楚如何做到这一点。以以下控制器为例(为清晰起见,请将其截短): } 注意,我只想验证是否已调度了正确的控制器和操作,但不希望实际插入记录。同样,我有删除等的等价物。。我不希望记录被删除 这里到底有什么需要嘲笑的?竞争模型、数据库适配器或模型工厂,还是全部三种?我如何注射这些?我尝试过(为

我正在为我的控制器编写一些单元测试(phpunit3.6),希望验证操作是否正确等等。。他们被解雇了。这很容易。但是,一些控制器还通过不需要的模型执行某些操作,例如将记录插入数据库

我知道我需要模仿这些,但不清楚如何做到这一点。以以下控制器为例(为清晰起见,请将其截短):

}

注意,我只想验证是否已调度了正确的控制器和操作,但不希望实际插入记录。同样,我有删除等的等价物。。我不希望记录被删除

这里到底有什么需要嘲笑的?竞争模型、数据库适配器或模型工厂,还是全部三种?我如何注射这些?我尝试过(为了简洁起见,再次删节):

}


据我所知,PHPUnit神奇地用模拟替换了对原件的任何引用,因此,当发送被称为“假模拟”时,将在其位置使用模拟。这不会发生。有人能解释一下这是如何实现的吗?

看起来你的模拟设置正确。直到我看到你的问题并研究了一下,我才知道你可以从mocks返回mocks

这里发生的事情是,您需要使方法getModelFactory()返回模拟工厂的实例。现在它只是返回真实的东西

我不确定getModelFactory方法中发生了什么,所以我很难说如何重写它以使其返回模拟工厂

但也许你不必重写它。在我的ZF应用程序中,我不测试控制器,但要测试需要将内容保存到模型中的内容,我只需更改到配置文件中的测试数据库进行测试。我使用Doctrine1.2,所以我只在setUp()方法中启动一个事务,在tearDown()方法中启动一个回滚

我的测试数据库是完全空的,我基本上用一些特定于测试的工厂类在每个测试方法中创建必要的数据。缺点是它似乎确实占用了大量内存。我认为它在大约140个测试中达到了200MB,并且并非所有这些测试都需要数据库访问

我只是使用这个方法,因为它对我来说是最容易实现的,因为我只需要更改数据库配置。如果你不是在做一个非常大规模的项目,这可能对你有用。您还可以在内存中使用sqlite对测试数据库运行测试,这应该对您有用,因为您在测试中没有测试数据库。数据刚刚被插入,然后在测试结束时,它就消失了。在我的项目中,我使用一个MySQL测试数据库,因为我希望它尽可能接近生产中的数据库

示例(您可能没有使用条令。我只是说明如何使用事务和回滚来保持测试数据库处于一致状态):


是的,看看前面的答案。我完全同意。但是MySQL和Zend_Db不能实现同样的功能。这是因为Zend_Db没有嵌套事务。 所以,您唯一能做的就是使用测试数据库,并在每次测试后重建它


检查。

谢谢,是的,基本上我用配置模拟了工厂,这样单元测试就不用真正的东西了。
public function addAction()
{
    $data = $this->getRequest()->getPost();
    $model = $this->getModelFactory()->getCompetitionModel()->insert($data);    }
public function testAddActionIsDispatched()
{
    $this->request->setMethod('POST');
    $this->request->setPost(array($data…));

            $modelMock = $this->getMockBuilder('Competition_Adder')
                 ->disableOriginalConstructor()
                 ->getMock();                


            $factoryMock = $this->getMockBuilder('ModelFactory')
                    ->disableOriginalConstructor()
                    ->getMock(); 

        // Configure the stub.
            $factoryMock->expects($this->any())
                ->method('getCompetitionModel')
                ->will($this->returnValue($modelMock));        

            $modelMock->expects($this->once())
                    ->method('insert')
                    ->will($this->returnValue(true));

            $this->dispatch('/mymodule/add/');
            $this->assertController('test');
            $this->assertAction('add');  
            $this->assertResponseCode(200);
}
public function setUp()
{
    $this->bootstrap = new Zend_Application(
        APPLICATION_ENV, APPLICATION_CONFIG);       
    parent::setUp();
    $bootstrap = $this->bootstrap->getBootstrap();

    $this->_conn = Doctrine_Manager::connection();
    $this->_conn->beginTransaction();
}

public function tearDown()
{
    $this->_conn->rollback();        
    $this->_conn->close();    
}