Seite 1 von 1

Unittests, Cacheobjekt, $phpbb_container

Verfasst: 13.02.2015 00:46
von gn#36
Zunächst vorweg: An der Stelle an der es gerade nicht funktioniert wäre die simple Lösung: "Wir lassen den Cache einfach weg, denn er wird eigentlich gerade eh nicht gebraucht." Aber es gibt noch andere Stellen, wo er doch nützlich wäre, für die habe ich nur gerade keinen Unit-Test.

Nehmen wir mal an, unsere Extension hat irgend ein Modul, dem ich in der services.yml ein Cache Objekt übergebe:

Code: Alles auswählen

    phpbbde.pastebin.cron.main:
        class: phpbbde\pastebin\cron\main
        arguments:
            - @cache
            - @config
            - @dbal.conn
            - @log
            - %phpbbde.pastebin.path%
            - %core.root_path%
            - %core.php_ext%
        calls:
            - [set_name, [phpbbde.pastebin.cron.main]]
        tags:
            - { name: cron.task }
Dieses Cache Objekt ist nun vom Typ phpbb\cache\service, der dementsprechend auch im Konstruktor der aufgerufenen Klasse definiert ist:

Code: Alles auswählen

public function __construct(\phpbb\cache\service $cache, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\log\log_interface $log, $pastebin_path, $root_path, $php_ext)
Das bedeutet, dass ein Unittest ebenfalls ein Objekt dieses Typs braucht, um die Klasse zu testen. Interessanterweise implementiert dieses Objekt aber nicht \phpbb\cache\driver\driver_interface, weshalb man es nicht einfach durch das Mock-Objekt ersetzen kann, obwohl es dank __call sämtliche Aufrufe einfach an den Driver weiterleitet und deshalb genauso agiert wie ein Objekt dieses Typs. Das wiederum führt dazu, dass ich ein neues Objekt vom Typ \phpbb\cache\service mit Mockobjekten füttern muss, so dass ich es in den Unittests benutzen kann:

Code: Alles auswählen

$cache = new \phpbb\cache\service($this->getMock('\phpbb\cache\driver\driver_interface'), $config, $db, $phpbb_root_path, $phpEx);
Gibt's da einen einfacheren Weg? Oder gibt's statt @cache was weniger aufgeblasenes? Ich brauche ja im Prinzip eh nur die Schnittstelle von \phpbb\cache\driver\driver_interface

Dazugehöriger Travis Build: https://travis-ci.org/gn36/phpbb-ext-pa ... s/50568549
Und die entsprechende Branch: https://github.com/gn36/phpbb-ext-paste ... /dev/tests

Noch eine weitere Frage dazu: Nehmen wir mal an, ich möchte ein paar in der services.yml definierte Parameter mit einem Unittest auf ihre Gültigkeit überprüfen:

Code: Alles auswählen

parameters:
    phpbbde.pastebin.path: %core.root_path%ext/phpbbde/pastebin/
    phpbbde.pastebin.geshi: %phpbbde.pastebin.path%vendor/easybook/geshi/
    phpbbde.pastebin.geshilangs: %phpbbde.pastebin.geshi%geshi/
    phpbbde.pastebin.cron.prune_interval: 86400
    tables.phpbbde.pastebin.pastebin: %core.table_prefix%pastebin
Wie komme ich an die Parameter ran? Für den Unittest von Klassen, die darauf zugreifen habe ich die Variablen im Test neu angelegt:

Code: Alles auswählen

$phpbb_container = new \phpbb_mock_container_builder();
        $params = array(
            'phpbbde.pastebin.path'         => $phpbb_root_path . 'ext/phpbbde/pastebin/',
            'phpbbde.pastebin.geshi'         => $phpbb_root_path . 'ext/phpbbde/pastebin/' . 'vendor/easybook/geshi/',
            'phpbbde.pastebin.geshilangs'     => $phpbb_root_path . 'ext/phpbbde/pastebin/' . 'vendor/easybook/geshi/' . 'geshi/',
            'phpbbde.pastebin.cron.prune_interval' => 86400,
            'tables.phpbbde.pastebin.pastebin' => 'phpbb_pastebin',
        );
        foreach($params as $name => $value)
        {
            $phpbb_container->setParameter($name, $value);
        } 
Aber das nützt mir natürlich nichts, wenn ich überprüfen will, ob die Parameter selbst in Ordnung sind.

Re: Unittests, Cacheobjekt, $phpbb_container

Verfasst: 13.02.2015 08:36
von nickvergessen
Ich würde einfach den Service an sich schon mocken und nicht erst den driver.

Code: Alles auswählen

$this->user = $this->getMockBuilder('\phpbb\cache\service')
    ->disableOriginalConstructor()
    ->getMock();
Und dann angeben was die jeweiligen Methoden zurück geben sollen, z.B.: https://github.com/nickvergessen/phpbb- ... st.php#L41

https://github.com/gn36/phpbb-ext-paste ... in.php#L74 bitte kein global verwenden.
Auch Parameter kann man einfach injecten ;) Damit brauchst du dann auch das Object \phpbb_mock_container_builder() nicht mehr erstellen.

Bzgl Parameter testen. Vllt hilft dir da https://github.com/phpbb/phpbb/blob/dev ... r_test.php weiter.

Re: Unittests, Cacheobjekt, $phpbb_container

Verfasst: 13.02.2015 10:43
von gn#36
Danke für die Rückmeldung. Ich sehe schon, ich muss da noch einiges mehr an Zeit rein investieren...