Phpunit部分模拟+代理实体

时间:2018-01-11 10:25:53

标签: php symfony unit-testing phpunit

我尝试找到问题的解决方案,但没有找到任何结果。

我使用: Symfony,Doctrine,PhpUnit

我有一个实体类InvoiceNumerator:

array(2) {
      ["www.test.pl"]=>
      array(3) {
        ["category"]=>
        array(3) {

        }
        ["category2"]=>
        array(3) {

        }
      }
      ["www.test2.pl"]=>
      array(3) {
        ["category"]=>
        array(3) {

        }
        ["category2"]=>
        array(3) {

        }
        ["category3"]=>
        array(3) {

        }
      }
    }

我需要在我的测试中模拟这个类,但是我的setter应该保持不变 - 没有存根 - 工作代码。 为了模拟这个类,我做了一个简单的模拟方法:

/**
 * InvoiceNumerator
 *
 * @ORM\Table(name="invoice_numerator")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\InvoiceNumeratorRepository")
 */
class InvoiceNumerator
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="translatedFormat", type="string", length=64)
     */
    private $translatedFormat;

    /**
     * @var int
     *
     * @ORM\Column(name="currentValue", type="integer", options={"default": 0})
     */
    private $currentValue = 0;

    /**
     * @var string
     *
     * @ORM\Column(name="current_number", type="string", length=64)
     */
    private $currentNumber = '';

    /**
     * Get id
     *
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set translatedFormat
     *
     * @param string $translatedFormat
     *
     * @return InvoiceNumerator
     */
    public function setTranslatedFormat($translatedFormat)
    {
        $this->translatedFormat = $translatedFormat;

        return $this;
    }

    /**
     * Get translatedFormat
     *
     * @return string
     */
    public function getTranslatedFormat()
    {
        return $this->translatedFormat;
    }

    /**
     * Set currentValue
     *
     * @param integer $currentValue
     *
     * @return InvoiceNumerator
     */
    public function setCurrentValue($currentValue)
    {
        $this->currentValue = $currentValue;

        return $this;
    }

    /**
     * Get currentValue
     *
     * @return int
     */
    public function getCurrentValue()
    {
        return $this->currentValue;
    }

    /**
     * @return string
     */
    public function getCurrentNumber(): string
    {
        return $this->currentNumber;
    }

    /**
     * @param string $currentNumber
     * @return InvoiceNumerator
     */
    public function setCurrentNumber(string $currentNumber): InvoiceNumerator
    {
        $this->currentNumber = $currentNumber;
        return $this;
    }
}

但在这种情况下,我的安装人员无法正常工作。 我还可以在新的Entity对象上设置值:

public function getInvoiceNumerator()
{
    $invoiceNumerator = $this->createMock(InvoiceNumerator::class);

    $invoiceNumerator->method('getTranslatedFormat')
        ->willReturn('FS-CM/{n}/2018/01');

    $invoiceNumerator->method('getCurrentValue')
        ->willReturn('1');

    $invoiceNumerator->method('getCurrentNumber')
        ->willReturn('FS-CM/1/2018/01');

    return $invoiceNumerator;
}

在这种情况下,我的二传手正常工作。

问题:

有没有更好的方法呢?什么是最佳做法?

2 个答案:

答案 0 :(得分:1)

基本上,您可以将模拟设置为仅模拟特定方法:

 $invoiceNumerator = $this->getMockBuilder(InvoiceNumerator::class)
                      ->setMethods(["getTranslatedFormat","getCurrentValue", "getCurrentNumber"])
                      ->getMock();

根据the documentation

  可以在Mock Builder对象上调用

setMethods(array $methods)来指定要用可配置的测试double替换的方法。其他方法的行为不会改变。如果调用setMethods(null),则不会替换任何方法。

答案 1 :(得分:1)

你几乎在你的问题“Phpunit partial mock + proxy Entity”中得到答案:你可以使用createPartialMock()方法:

$invoiceNumerator = $this-> createPartialMock(
    InvoiceNumerator::class,
    ['nameOfMockedMethod1', 'nameOfMockedMethod2']
);

此方法已在PHPUnit 5.5及更高版本中提供。如果您使用的是旧版本,则可以使用setMethods(),但必须根据getMockBuilder()返回的结果调用它,而不是createMock()返回的对象(这是从第一个答案尝试接近后得到的错误):

$subject = $this->getMockBuilder(MyClass::class)
    ->setMethods(['method1', 'method2'])
    ->getMock();

但是,请注意createPartialMock()稍微多一些。例如,它会自动禁用原始构造函数 - 这几乎总是你在测试中想要的(以及使用setMethods()时你必须​​做的事情)。有关确切信息,请参阅文档。