PHP单元测试来自不同类的外部静态方法调用


PHP unit testing External static method call from different class

我正试图为一个函数编写一个单元测试,该函数会立即从另一个使用函数输入作为参数的类中加载对象。我是php单元测试的新手,找不到任何能解决我特定问题的东西。我有几条线索都没有用,那就是使用注射器,并试图让我们反思。

我试图为其编写单元测试的代码是:

public static function isUseful($item) {
  $objPromo = MyPromoCodes::Load($item->SavedSku);
  if (!is_null($objPromo)
    && ($objPromo->PromoType == MyPromoCodes::Interesting_Promo_Type)) {
    return true;
  }
  return false;
}

我试图嘲笑这一点:

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));
}

但是,这不起作用,因为该对象没有set方法。。。。

不知道还能尝试什么,任何帮助都将不胜感激。

我制作了一个使静态类模拟成为可能的库:

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'));
    }
}

首先,您不能用PHPUnit模拟静态方法。至少4.x和5.x 没有

我建议采用这样的DI方法:

class MyClass
{
    private $promoCodesRepository;
    public function __construct(MyPromoCodesRepository $promoCodesRepository)
    {
        $this->promoCodesRepository = $promoCodesRepository;
    }
    public function isUseful(MyItem $item)
    {
        $objPromo = $this->promoCodesRepository->Load($item->SavedSku);
        // ...
    }
}

在这里,您可以轻松地模拟Load方法。

不幸的是,"静态"方法在测试过程中会产生很多问题,因此最好尽可能避免。