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

Thursday, January 6, 2022

[FIXED] What is the best practice to use expectations on mocked objects in controllers

 January 06, 2022     cakephp, cakephp-3.0, phpunit     No comments   

Issue

I often want to mock out a Component or Object in a controller. I use the controllerSpy method to do that like this:

public function controllerSpy($event, $controller = null)
{
    parent::controllerSpy($event, $controller);

    $OrderConfirmation = $this->getMockBuilder('OrderConfirmation')
        ->setMethods(['send'])
        ->getMock();
    $OrderConfirmation->expects($this->once())->method('send');
    $this->_controller->OrderConfirmation = $OrderConfirmation;
}

The Problem is that the expectation that the send-Method is called is set in every test. But it depends on the scenario, there are scenarios where the confirmation shall not be sent. I would like to configure the expectation in the test itself and not globally in the controllerSpy method. Something like this:

public function testAddOrder()
{
    $this->_controller->OrderConfirmation->expects($this->once())->method('send');
    $this->post('/add_order');
}

But the problem her is that the expectation will be lost, since the whole OrderConfirmation object is overwritten later. Has anybody solved this problem before?


Solution

You could just listen to the Controller.initialize event, that's what the test dispatcher does too:

public function testAddOrder()
{
    \Cake\Event\EventManager::instance()->on(
        'Controller.initialize',
        function (\Cake\Event\EventInterface $event) {
            /** @var \Cake\Controller\Controller $controller */
            $controller = $event->getSubject();
            
            // ...

            $controller->OrderConfirmation = $OrderConfirmation;
        }
    );

    $this->post('/add_order');
}

Or implement for example a callback for the controllerSpy() method, something like this:

protected $controllerSpyCallback;

public function controllerSpy($event, $controller = null)
{
    parent::controllerSpy($event, $controller);

    if (is_callable($this->controllerSpyCallback)) {
        $this->controllerSpyCallback($this->_controller);
    }
}

public function testAddOrder()
{
    $this->controllerSpyCallback = function (\Cake\Controller\Controller $controller) {
        // ...
        
        $controller->OrderConfirmation = $OrderConfirmation;
    };

    $this->post('/add_order');
}


Answered By - ndm
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

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