繁体   English   中英

PHPSpec与Mock示例测试始终返回null,但实现按预期工作

[英]PHPSpec with Mock example test always returns null but implementation works as expected

我想从PHPSpec开始,所以我正在研究两个简单的类。 第一个负责对数量应用缩小或放大百分比,第二个负责使用百分比应用程序(例如模拟)来计算产品价格。

PercentageToNumberApplyerSpec(规范):

namespace spec\My;

use PhpSpec\ObjectBehavior;
use Prophecy\Argument;

class PercentageToNumberApplyerSpec extends ObjectBehavior
{
    function it_is_initializable()
    {
        $this->shouldHaveType('My\PercentageToNumberApplyer');
    }

    function it_enlarges_a_number_with_a_given_percentage()
    {
        $this->enlarge(100, 20)->shouldReturn(120);
        $this->enlarge(80, 25)->shouldReturn(100);
        $this->enlarge(20, 50)->shouldReturn(30);
    }

    function it_reduces_a_number_with_a_given_percentage()
    {
        $this->reduce(100, 20)->shouldReturn(80);
        $this->reduce(80, 10)->shouldReturn(72);
        $this->reduce(250, 20)->shouldReturn(200);
    }
}

PercentageToNumberApplyer(实现):

<?php

namespace My;

class PercentageToNumberApplyer
{
    /**
     * Enlarge given number with a given percentage
     *
     * @param $number
     * @param $percentage
     * @return float
     */
    public function enlarge($number, $percentage)
    {
        return $this->calculate($number, $percentage) + $number;
    }

    /**
     * Reduce given number with a given percentage
     *
     * @param $number
     * @param $percentage
     * @return mixed
     */
    public function reduce($number, $percentage)
    {
        return $number - $this->calculate($number, $percentage);
    }

    /**
     * @param $number
     * @param $percentage
     * @return float
     */
    private function calculate($number, $percentage)
    {
        return $number * $percentage / 100;
    }
}

PriceCalculatorSpec(规格):

<?php

namespace spec\My;

use My\PercentageToNumberApplyer;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;

class PriceCalculatorSpec extends ObjectBehavior
{
    function let(PercentageToNumberApplyer $percentageToNumberApplyer)
    {
        $this->beConstructedWith($percentageToNumberApplyer);
    }

    function it_calculates_price_discount($percentageToNumberApplyer)
    {
        $number = 100;
        $discount = 20;

        $percentageToNumberApplyer->reduce($number, $discount)->shouldBeCalled();

        $this->applyDiscountTo($number, $discount)->shouldReturn(80);
    }
}

问题

问题是在上面的示例中,运行phpspec后,运行结果为:

- it calculates price discount
expected [integer:80], but got null

PriceCalculator(实现):

<?php

namespace My;

class PriceCalculator
{
    /**
     * @var PercentageToNumberApplyer
     */
    private $percentageToNumberApplyer;

    /**
     * @param PercentageToNumberApplyer $percentageToNumberApplyer
     */
    public function __construct(PercentageToNumberApplyer $percentageToNumberApplyer)
    {
        $this->percentageToNumberApplyer = $percentageToNumberApplyer;
    }

    /**
     * @param $basePrice
     * @param $discount
     * @return mixed
     */
    public function applyDiscountTo($basePrice, $discount)
    {
        return $this->percentageToNumberApplyer->reduce($basePrice, $discount);
    }
}

为什么以下用例仍然有效,即使测试失败:

$priceCalculator = new \My\PriceCalculator(new \My\PercentageToNumberApplyer());

$price = $priceCalculator->applyDiscountTo(100, 20);

$ price具有80的价值...

您不需要您的情况下的模拟。 存根就可以。 阅读有关PHP中的测试加倍的更多信息。

而不是模拟通话:

$percentageToNumberApplyer->reduce($number, $discount)->shouldBeCalled();

存根:

$percentageToNumberApplyer->reduce($number, $discount)->willReturn(80);

接下来,您只需要期望实际返回的是计算得出的结果:

$percentageToNumberApplyer->reduce($number, $discount)->willReturn(80);

$this->applyDiscountTo($number, $discount)->shouldReturn(80);

这是因为您不必在意是否拨打了电话。 您只对结果感兴趣。

根据经验,您通常会:

  • 模拟执行动作的协作者(命令方法)
  • 返回内容的存根协作者(查询方法)

在大多数情况下,最好在两者之间进行分隔(命令/查询分隔),并且我们不需要同时模拟和存根。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM