Magento2 PHPUnit – How to Write a Unit Test for an Admin Controller

magento2phpunit

How can I test the content of my controller via a unit test?

The controller has an execute-function. If my content phtml file contains "Hello World" or a page title "My Title" is configured in the xml file, my understanding is that I could write a unit test which checks that by a simple string comparison:


    public function execute()
    {
        return  $resultPage = $this->resultPageFactory->create();
    }

Now … I do not know how to figure out how to get the html content or title out of the $resultPage element, and I also do not know how I can write a test function for this. Any ideas?

Best Answer

I have evaluated an answer with my colleagues: Unit tests are not really appropriate for the controller execute() method. Unit tests would test a method without references to other methods. The execute() method needs the entire Magento framework to run, and therefore can only be tested with an integration test.

Let's say we have a simple test controller src/app/code/Mycompany/Mymodule/Controller/Adminhtml/Demo/Index.php:


/**
 * Module name.
 *
 * @category Mage
 */

namespace Mycompany\Mymodule\Controller\Adminhtml\Demo;

class Index extends \Magento\Backend\App\Action
{
    /**
     * @var \Magento\Framework\View\Result\PageFactory
     */
    private $resultPageFactory;

    /**
     * Constructor.
     *
     * @param \Magento\Backend\App\Action\Context        $context
     * @param \Magento\Framework\View\Result\PageFactory $resultPageFactory
     */
    public function __construct(
        \Magento\Backend\App\Action\Context $context,
        \Magento\Framework\View\Result\PageFactory $resultPageFactory
    ) {
        parent::__construct($context);
        $this->resultPageFactory = $resultPageFactory;
    }

    /**
     * Load the page defined in view/adminhtml/layout/mymodule_demo_index.xml.
     *
     * @return \Magento\Framework\View\Result\Page
     */
    public function execute()
    {
        return  $resultPage = $this->resultPageFactory->create();
    }
}

We can then create a very simple integration test in src/app/code/Mycompany/Mymodule/Test/Integration/Controller/Adminhtml/Demo/ViewTest.php:


namespace Mycompany\Mymodule\Test\Integration\Controller\Adminhtml;

/**
 * @covers \Magento\Mymodule\Controller\Adminhtml\Mymodule\Index
 */
class IndexTest extends \Magento\TestFramework\TestCase\AbstractController
{
    private $objectManager;
    protected function setUp() {
    }

    /**
     * Tests if the new controller returns an object of the correct type
     * This test might not be super necessary, but at least it runs that code
     * and would let us know if there'd be a major issue.
     */
    public function testIfControllerReturnsPageInterceptor()
    {
        $page = $this->_objectManager->get(\Mycompany\Mymodule\Controller\Adminhtml\Demo\Index::class);
        $this->assertEquals(
            'Magento\Backend\Model\View\Result\Page\Interceptor',
            get_class($page->execute())
        );
    }
}

Update: I just received a better version of the actual test function. AssertInstanceOf is probably the better way to test it:


public function testIfControllerReturnsPageInterceptor()
    {
        $page = $this->_objectManager->get(\Mycompany\Mymodule\Controller\Adminhtml\Demo\Index::class);
        $this->assertInstanceOf(\Magento\Backend\Model\View\Result\Page::class, $page->execute());
    }
Related Topic