Admin Session mocken mit EcomDev_PHPUnit in Magento Enterprise

In Integrationstests mit EcomDev_PHPUnit_Test_Case_Controller gibt es eine praktische Helper-Methode adminSession(), um Requests im Magento Backend zu testen. Mit Magento Enterprise kann es da allerdings zu dieser Fehlermeldung kommen:

Exception: Warning: in_array() expects parameter 2 to be array, null given in /home/vagrant/mwdental/www/app/code/core/Enterprise/AdminGws/Model/Role.php on line 83

So gesehen in Magento EE 1.14.1.

Ohne Details zu den Enterprise-Modulen preiszugeben, hier eine Lösung in der der schuldige Observer gemockt wird:

$adminObserverMock = $this->getModelMock(
    'enterprise_admingws/observer',
    array('adminControllerPredispatch'));
$adminObserverMock->expects($this->any())
    ->method('adminControllerPredispatch')
    ->will($this->returnSelf());
$this->replaceByMock('singleton', 'enterprise_admingws/observer',
    $adminObserverMock);
$this->adminSession();

Magento: Block-Inhalt verschwindet nach core_block_to_html_after Event

Vorsicht mit Mage_Core_Block_Abstract::toHtml() innerhalb eines Observers für core_block_to_html_after! Ich habe die Methode genutzt, um HTML aus einem Block in einen existierenden Block zu injizieren, mit dem Ergebnis dass alles außer diesem neuen Block von der Ausgabe entfernt wurde.

Beim Debugging im Core habe ich die Ursache darin gefunden, wie das Event dispatched wird:

        /**
         * Use single transport object instance for all blocks
         */
        if (self::$_transportObject === null) {
            self::$_transportObject = new Varien_Object;
        }
        self::$_transportObject->setHtml($html);
        Mage::dispatchEvent('core_block_abstract_to_html_after',
            array('block' => $this, 'transport' => self::$_transportObject));
        $html = self::$_transportObject->getHtml();

Wie man sieht, ist das Transport-Objekt, das genutzt wird um Änderungen am HTML in Observern zu ermöglichen, eine Klassenvariable von Mage_Core_Block_Abstract, und verhält sich ähnlich wie ein Singleton. Ich kann mir keinen guten Grund dafür denken aber es riecht verdächtig nach premature optimization.

Was nun passiert ist, dass während das Event verarbeitet wird, der neue Block seine eigene Ausgabe in seinem eigenen toHtml() Aufruf dem selben Transport-Objekt zuweist und die ursprüngliche Ausgabe verloren geht, wenn man sie nicht vorher gesichert hat.

Die Lösung für mein konkretes Problem war, den Block an anderer Stelle zu erstellen und vorzurendern, aber wenn das nicht getan wird, muss die Ausgabe direkt zu Beginn im Observer in eine neue Variable kopiert werden:

$html = $observer->getTransport()->getHtml(); // should be the first statement

// now you can do what you want, create other blocks, modifiy $html ...

$observer->getTransport()->setHtml($html); // should be the last statement

Retrospektive: Das Blog 2014

Ein privat und geschäftlich erfolgreiches Jahr ist herum und das neue fängt erst langsam an. Zeit, darauf zurück zu blicken wie das Blog seit dem Relaunch meiner Seite letzten Februar läuft und neue Ziele für 2015 zu stecken.

Angesagte Themen

Einige Themen stachen auf die ein oder andere Art hervor:

Unit Testing

Mein Allzeit-Top-Artikel von 2011 [PHP] Mocking Built-in Functions Like time() In Unit Tests war 2014 immer noch der zweitmeist besuchte Artikel und ich freue mich, dass das darin vorgestellte Konzept einige neue Aufmerksamkeit erfahren hat:

  • Matthew Weier O’Phinney (@mwop) nutze es, um Code zu testen, der Ausgaben erzeugt. Siehe PHP: header() mocken, um Controller zu Unit-testen
  • Markus Malkusch hat inspiriert durch meinen Artikel eine Bibliothek zum mocken von Funktionen entwickelt, php-mock. Dabei fand und dokumentierte er auch einen weiteren Sonderfall, bei dem es nicht funktioniert (aktuell ein offener PHP Bug).

PHP 5.3 Death March

Der kontroverseste, meist diskutierte und meist geklickte Artikel 2014 war meine Ankündigung, PHP 5.3 Support fallenzulassen wo immer möglich, um Adaption von aktuellen PHP Versionen voranzutreiben (5.3 hat August 2014 sein end-of-life erreicht und bekommt seitdem keine Sicherheits-Fixes mehr).

Ich fühle mich in guter Gesellschaft weil kurz darauf Anthony Ferrara (@ircmaxell) die selbe Diskussion in größerem Umfang auf Twitter und anderswo mit seinen Artikeln zu PHP Versionen anstieß:

  1. On PHP Version Requirements
  2. Being A Responsible Developer
  3. PHP Install Statistics

Vagrant

puphpet-vagrant-puppet-magentoIch habe eine Serie über Vagrant geschrieben, speziell um es Magento-Entwicklern nahezubringen, veröffentlicht auf integer-net.de. Eine englische Zusammenfassung gab es im Webguys Adventskalender: Türchen 19: Kickstart your Magento Dev System with Vagrant. Zwei der vier Teaser in diesem Blog haben es in die Top Ten 2014 geschafft (siehe unten).
Continue reading “Retrospektive: Das Blog 2014”