duebstep
duebstep

Reputation: 197

PHP unit testing External static method call from different class

I am trying to write a unit test for a function that immediately loads an object from a different class that uses the input to the function as a parameter. I am new to php unit testing and couldn't find anything that address my particular problem. A few leads that I had that led to no avail was using an injector, and trying to us a reflection.

The code I am trying to write a unit test for is:

public static function isUseful($item) {

  $objPromo = MyPromoCodes::Load($item->SavedSku);

  if (!is_null($objPromo)
    && ($objPromo->PromoType == MyPromoCodes::Interesting_Promo_Type)) {
    return true;
  }
  return false;
}

My attempt at mocking this out:

public function testIsUseful() {

  $injector = $this->getMockBuilder('MyPromoCodes')
    ->setMethods(array('Load'))
    ->getMock();
  $objPromo = $this->getMock('MyPromoCodes');
  $objPromo->PromoType = 'very interesting promo type';
  $injector->set($objPromo, 'MyPromoCodes');

  $lineItem1 = $this->getDBMock('LineItem');


  $this->assertTrue(MyClass::isUseful($lineItem1));

}

however this doesn't work because there is no set method for this object....

Not sure what else to try, any help would be appreciated.

Upvotes: 0

Views: 1569

Answers (2)

Leonid Shagabutdinov
Leonid Shagabutdinov

Reputation: 1110

I made the library that makes static classes mocking possible:

class MyClass {

    public static $myPromoCodes = 'myPromoCodes';

    public static function isUseful($item) {

      $objPromo = self::$MyPromoCodes::Load($item->SavedSku);

      if (!is_null($objPromo)
        && ($objPromo->PromoType == MyPromoCodes::Interesting_Promo_Type)) {
        return true;
      }
      return false;
    }

}

class MyClassTest extends \PHPUnit_Framework_TestCase
{
    public function testSomething()
    {
        $myClass = Moka::stubClass('MyClass');
        $myClass::$myPromoCodes = Moka::stubClass(null, ['::Load' => (object)[ 
            'PromoType' => MyPromoCodes::Interesting_Promo_Type
        ]]);
        $this->assertTrue($myClass::isUseful((object)['SavedSku' => 'SKU']);
        $this->assertEquals([['SKU']], $myClass::$myPromoCodes->moka->report('::Load'));
    }
}

Upvotes: 1

Aleksander Wons
Aleksander Wons

Reputation: 3967

To start with you cannot mock static method with PHPUnit. At least not with 4.x and 5.x.

I would suggest a DI approach like this:

class MyClass
{
    private $promoCodesRepository;

    public function __construct(MyPromoCodesRepository $promoCodesRepository)
    {
        $this->promoCodesRepository = $promoCodesRepository;
    }

    public function isUseful(MyItem $item)
    {
        $objPromo = $this->promoCodesRepository->Load($item->SavedSku);

        // ...
    }
}

Here you can easily mock the Load method.

Unfortunately the "static" approach creates a lot of issues during tests so it is better to avoid it whenever possible.

Upvotes: 0

Related Questions