DEV Community

loading...

PHPUnit - How to unit test a method with no return value?

farhanrosenborg profile image farhan ・2 min read

When writing unit test for one public function in my class. I was a bit confused about how to test a function which has no return value(s). Normally unit tests validate return of boolean value, arrays or some object. There are parts of code which test of Exceptions being thrown from a function. In this scenario I was not throwing any exception or returning a value. What I wanted to test though if certain functionality was executed or not executed when function was being called.

Example code of a function returning void

class UpdateShipmentTracking
{
    private $tracking;

    /**
     * UpdateShipmentTracking constructor.
     * @param Tracking $tracking
     */
    public function __construct(
        Tracking $tracking
    ) {
        $this->tracking = $tracking;
    }

    /**
     * @param array $orders
     */
    public function send(array $orders): void
    {
        /** @var Order $order */
        foreach ($orders as $order) {
            $this->tracking->track($order->getRealOrderId());
        }
    }
}

// @note this class is being mocked in UpdateShipmentTrackingTest
class Tracking
{
    /**
     * @param string $orderID
     */
    public function track(string $orderID): void
    {
        // add shipment tracking number to order
    }
}
Enter fullscreen mode Exit fullscreen mode

Class UpdateShipmentTracking has the following things

  • It has a constructor injection of class Tracking.
  • It has a function called send which does not return anything. If array is not empty it updates the shipment tracking number.

How can we test a function like this, to be sure that it is functioning properly? If we observe the code properly there are 2 possibilities that can happen when the send function will be called.

Possibility 1
If we pass empty array to the function. Nothing will be executed. The track function of class Tracking will never be called.

Possibility 2
If we pass 1 element in the array. The track function of class Tracking will be called 1 time.

Now that we can see the possibilities. We can test the 2 scenarios. By doing so we cover that the function returning void is properly tested. If you do not believe my statement the screenshot of code coverage will prove that this is indeed true.

class UpdateShipmentTrackingTest extends TestCase
{
    /** @var Tracking */
    private $tracking;

    protected function setUp(): void
    {
        $this->tracking = $this->createMock(Tracking::class);
    }

    public function testEmptyOrdersArrayIsPassedNothingHappens(): void
    {
        // @note we do not expect function track to be called
        $this->tracking->expects($this->never())
            ->method('track');

        $object = $this->getUpdateShipmentTracking();
        $object->send([]);
    }

    public function testShipmentTrackingNumberWasAdded(): void
    {
        // @note we expect track to be called 1 time, since we pass 1 order
        $this->tracking->expects($this->exactly(1))
            ->method('track');

        $order = $this->createMock(Order::class);

        $order->expects($this->exactly(1))
            ->method('getRealOrderId')
            ->willReturn('100001');

        $object = $this->getUpdateShipmentTracking();
        $object->send([$order]);
    }

    /**
     * @return UpdateShipmentTracking
     */
    private function getUpdateShipmentTracking(): UpdateShipmentTracking
    {
        $objectManager = new ObjectManager($this);

        return $objectManager->getObject(UpdateShipmentTracking::class,
            [
                'tracking' => $this->tracking,
            ]);
    }
}
Enter fullscreen mode Exit fullscreen mode

Article original published on: http://rosenborgsolutions.com/phpunit-testing-return-void.php

Discussion

pic
Editor guide