cakephp3 test component在非对象上调用on()上的成员函数

cakephp3 test component在非对象上调用on()上的成员函数

问题描述:

I'm trying to test my plugin component written for cakephp 3.

This is my component:

namespace CurrencyConverter\Controller\Component;

use Cake\Controller\Component;
use Cake\Datasource\ConnectionManager;
use Cake\ORM\TableRegistry;

class CurrencyConverterComponent extends Component
{
    public $controller = null;

    public function setController($controller)
    {
        $this->controller = $controller;
    }

    public function startup($event)
    {
        $this->setController($event->subject());
    }


    public function convert($fromCurrency, $toCurrency, $amount, $saveIntoDb = 1, $hourDifference = 1, $dataSource = 'default') {

    }
}

and this is mt test:

namespace App\Test\TestCase\Controller\Component;

use CurrencyConverter\Controller\Component\CurrencyConverterComponent;
use Cake\Controller\Controller;
use Cake\Controller\ComponentRegistry;
use Cake\Network\Request;
use Cake\Network\Response;
use Cake\TestSuite\TestCase;

class CurrencyConverterComponentTest extends TestCase {
    public $fixtures = ['app.currencyconverter'];
    public $CurrencyConverter = null;
    public $controller = null;

    public function setUp() {
        parent::setUp();
        // Setup our component and fake test controller
        $request = new Request();
        $response = new Response();
        $this->controller = $this->getMock(
            'Cake\Controller\Controller',
            [],
            [$request, $response]
        );
        $registry = new ComponentRegistry($this->controller);
        $this->CurrencyConverter = new CurrencyConverterComponent($registry);
    }

    public function testAmountWithComma() {
        $fromCurrency   = 'EUR';
        $toCurrency     = 'GBP';
        $amount         = '20,00';
        $saveIntoDb     = 0;
        $hourDifference = 0;
        $dataSource     = 'test';

        $result = $this->CurrencyConverter->convert($fromCurrency, $toCurrency, $amount, $saveIntoDb, $hourDifference, $dataSource);

        $this->assertGreaterThan($result, $amount);
    }
}

When I run tests I get this error in the core!!

Fatal error:  Call to a member function on() on a non-object in /Users/alessandrominoccheri/Sites/cakephp3/vendor/cakephp/cakephp/src/Controller/Controller.php on line 289

How can I solve this?

Thanks

I this particular case you are mocking too much. You are telling phpunit to mock all methods in the controller, including the eventManager() getter method, which makes the controller try to call on() on a null object.

You need to only mock the methods you are interested in testing, that will alter the environment, or try to communicate with external services. Also, it seems like you are trying to test the Component instead of the Controller, the purpose of the test is not very clear.

To me, it seems like your CurrencyConverter class should not be a component, but just a class in your project that you could use anywhere. There is no need to attach such a class to controllers.