phpspec对非对象上的成员函数的调用


phpspec Call to a member function on a non-object

我对Symfony和phpspec还很陌生,所以请随意批评。所以问题是,我经常收到PHP致命错误:在非对象上调用成员函数write()。

基本上,被测试的类应该将输出写入控制台。在构造函数中,我首先创建流,然后将此流传递给另一个类,该类负责控制台中的输出。这是主代码。

类屏幕截图获取程序

<?php
namespace Bex'Behat'ScreenshotExtension'Service;
use Behat'Mink'Mink;
use Behat'Testwork'Output'Printer'StreamOutputPrinter;
use Bex'Behat'ScreenshotExtension'Driver'ImageDriverInterface;
use Behat'Testwork'Output'Printer'Factory'ConsoleOutputFactory;
/**
 * This class is responsible for taking screenshot by using the Mink     session
 *
 * @license http://opensource.org/licenses/MIT The MIT License
 */
class ScreenshotTaker
{
    /** @var Mink $mink */
    private $mink;
    /** @var ConsoleOutputFactory $output */
    private $output;
    /** @var ImageDriverInterface[] $imageDrivers */
    private $imageDrivers;
    /** @var StreamOutputPrinter $outputStream */
    private $outputStream;
    /**
     * Constructor
     *
     * @param Mink $mink
     * @param ConsoleOutputFactory $output
     * @param ImageDriverInterface[] $imageDrivers
     */
    public function __construct(Mink $mink, ConsoleOutputFactory $output, array $imageDrivers)
    {
        $this->mink = $mink;
        $this->output = $output;
        $this->imageDrivers = $imageDrivers;
        $this->outputStream = new StreamOutputPrinter ($output);
    }
    /**
     * Save the screenshot as the given filename
     *
     * @param string $fileName
     */
    public function takeScreenshot($fileName = 'failure.png')
    {
        try {
            $screenshot = $this->mink->getSession()->getScreenshot();
            foreach ($this->imageDrivers as $imageDriver) {
                $imageUrl = $imageDriver->upload($screenshot, $fileName);
                $this->outputStream->writeln('Screenshot has been taken. Open image at ' . $imageUrl);
            }
        } catch ('Exception $e) {
            $this->outputStream->writeln($e->getMessage());
        }
    }
}

现在这是phpspec测试。我正在传递构造函数中使用的ConsoleOutputFactory,但我得到了

PHP致命错误:对中的非对象调用成员函数write()125 线上的Behat/Testwork/Output/Printer/StreamOutputPrinter.php

此写入方法是StreamOutputPrinter的一部分。你能告诉我我这里缺了什么吗?

截图TakerSpec

<?php
namespace spec'Bex'Behat'ScreenshotExtension'Service;
use PhpSpec'ObjectBehavior;
use Prophecy'Argument;
use Behat'Mink'Mink;
use Behat'Mink'Session;
use Behat'Testwork'Output'Printer'Factory'ConsoleOutputFactory;
use Bex'Behat'ScreenshotExtension'Driver'Local;
use Behat'Testwork'Output'Printer'StreamOutputPrinter;
/**
 * Unit test of the class ScreenshotTaker
 *
 * @license http://opensource.org/licenses/MIT The MIT License
 */
class ScreenshotTakerSpec extends ObjectBehavior
{
    function let(Mink $mink, ConsoleOutputFactory $output, Local $localImageDriver)
    {
        $this->beConstructedWith($mink, $output, [$localImageDriver]);
    }
    function it_is_initializable()
    {
        $this->shouldHaveType('Bex'Behat'ScreenshotExtension'Service'ScreenshotTaker');
    }
    function it_should_call_the_image_upload_with_correct_params(Mink $mink, Session $session, Local $localImageDriver)
    {
        $mink->getSession()->willReturn($session);
        $session->getScreenshot()->willReturn('binary-image');
        $localImageDriver->upload('binary-image', 'test.png')->shouldBeCalled();
        $this->takeScreenshot('test.png');
    }
}

您应该模拟对StreamOutputPrinter第144行中的outputFactory->createOutput()的调用,但模拟另一个类中的东西是一种气味。因此,我建议将流逻辑移动到一个新的类,例如StreamOutputPrinterFactory,并注入这个工厂:

    public function __construct(Mink $mink, StreamOutputPrinterFactory $factory, array $imageDrivers)
{
    $this->mink = $mink;
    $this->imageDrivers = $imageDrivers;
    $this->outputStream = $factory->createNew();
}

现在,您可以模拟对$this->outputStream的任何调用。

您还应该在需要时调用createNew(),而不是在构造函数中。如果你需要进一步的帮助,请告诉我。