سؤال

I am writing a unit test for an observer invoking sales_order_place_after event.

SendOrderToVenuePay Observer

class SendOrderToVenuePay implements \Magento\Framework\Event\ObserverInterface
{
    public function __construct(
        \Sample\Module\Helper\Credit\Config $helperCreditConfig,
        \Sample\Module\Helper\Credit $helperCredit,
        \Magento\Customer\Helper\Session\CurrentCustomer $currentCustomer,
        \Sample\Module\Api\CreditManagementInterface $creditManagement
    ) {
        $this->helperCreditConfig = $helperCreditConfig;
        $this->helperCredit = $helperCredit;
        $this->currentCustomer = $currentCustomer;
        $this->creditManagement = $creditManagement;
    }

    /**
     * @param \Magento\Framework\Event\Observer $observer
     */
    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        $order = $observer->getEvent()->getOrder();
        if ($this->currentCustomer->getCustomerId()) {
            // do some good stuff with order
        }
    }
}

SampleObserverTest

class SampleObserverTest extends \PHPUnit\Framework\TestCase
{
    public function setUp()
    {
        $objectManager = new ObjectManager($this);

        $this->helperCreditConfigMock = $this->createMock('\Sample\Module\Helper\Credit\Config');

        $this->helperCreditMock = $this->createMock('\Sample\Module\Helper\Credit');

        $this->currentCustomerMock = $this->getMockBuilder('\Magento\Customer\Helper\Session\CurrentCustomer')
            ->disableOriginalConstructor()
            ->setMethods(['getCustomerId'])
            ->getMock();

        $this->creditManagementMock = $this->createMock('\Sample\Module\Api\CreditManagementInterface');

        $this->sendOrderToVenuePay = $objectManager->getObject(
            'Sample\Module\Observer\SendOrderToVenuePay',
            [
                'helperCreditConfig' => $this->helperCreditConfigMock,
                'helperCredit' => $this->helperCreditMock,
                'currentCustomer' => $this->currentCustomerMock,
                'creditManagement' => $this->creditManagementMock
            ]
        );
    }

    public function testExecute()
    {
        $this->eventMock = $this->createPartialMock(
            \Magento\Framework\Event::class,
            ['getOrder']
        );
        $this->eventObserverMock = $this->createMock(
            \Magento\Framework\Event\Observer::class
        );
        $this->eventObserverMock
            ->expects($this->any())
            ->method('getEvent')
            ->willReturn($this->eventMock);

        $this->eventMock
            ->expects($this->atLeastOnce())
            ->method('getOrder')
            ->willReturn($this->returnSelf());

        $this->currentCustomerMock
            ->expects($this->atLeastOnce())
            ->method("getCustomerId")
            ->willReturn($this->any());
    }
}

Following block of code

$this->currentCustomerMock
    ->expects($this->atLeastOnce())
    ->method("getCustomerId")
    ->willReturn($this->any());

throws

1) Sample\Module\Test\Observer\SampleObserverTest::testExecute
Expectation failed for method name is equal to "getCustomerId" when invoked at least once.
Expected invocation at least once but it never occurred.

and following block of code

$this->eventMock
    ->expects($this->atLeastOnce())
    ->method('getOrder')
    ->willReturn($this->returnSelf());

throws

1) Sample\Module\Test\Observer\SampleObserverTest::testExecute
Expectation failed for method name is equal to "getOrder" when invoked at least once.
Expected invocation at least once but it never occurred.

Please help what I am doing wrong? Since I am new to PHPUnit I am unable to figure it out.

هل كانت مفيدة؟

المحلول

You never execute your object i.e. $this->sendOrderToVenuePay, to execute this you have to initiated the observer object so right after $this->sendOrderToVenuePay declaretion under setUp() initiate observer object like below

$this->event = new \Magento\Framework\DataObject();
$this->observer = new \Magento\Framework\Event\Observer(['event' => $this->event]);

2nd, replace everything in testExecute with the following code

$this->currentCustomerMock->expects($this->atLeastOnce())
    ->method("getCustomerId")
    ->willReturn(1);

$this->assertEquals($this->sendOrderToVenuePay, $this->sendOrderToVenuePay->execute($this->observer));

The test will be passed successfully but remember if you want to do some good stuff with the order then you must assign an order to event observer to perform further tests, add following lines just before the $this->assertEquals

/** @var \Magento\Sales\Model\Order | \PHPUnit\Framework\MockObject\MockObject $orderMock */
$orderMock = $this->getMockBuilder(\Magento\Sales\Model\Order::class)
    ->disableOriginalConstructor()
    ->getMock();
$this->event->setOrder($orderMock);

Since we are using \Magento\Framework\DataObject so setOrder will act as a magic setter.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى magento.stackexchange
scroll top