我对Symfony和phpspec还很陌生,所以请随意批评。所以问题是,我经常收到PHP致命错误:在非对象上调用成员函数write()。
基本上,被测试的类应该将输出写入控制台。在构造函数中,我首先创建流,然后将此流传递给另一个类,该类负责控制台中的输出。这是主代码。
类屏幕截图获取程序:
<?php
namespace BexBehatScreenshotExtensionService;
use BehatMinkMink;
use BehatTestworkOutputPrinterStreamOutputPrinter;
use BexBehatScreenshotExtensionDriverImageDriverInterface;
use BehatTestworkOutputPrinterFactoryConsoleOutputFactory;
/**
* 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 specBexBehatScreenshotExtensionService;
use PhpSpecObjectBehavior;
use ProphecyArgument;
use BehatMinkMink;
use BehatMinkSession;
use BehatTestworkOutputPrinterFactoryConsoleOutputFactory;
use BexBehatScreenshotExtensionDriverLocal;
use BehatTestworkOutputPrinterStreamOutputPrinter;
/**
* 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('BexBehatScreenshotExtensionServiceScreenshotTaker');
}
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()
,而不是在构造函数中。如果你需要进一步的帮助,请告诉我。