我正在构建一个需要直接访问composer的php应用程序。但是,为了测试应用程序,我实际上不想运行composer,所以我试图模拟它。
<?php
namespace MyNamespace;
use Composer\Console\Application;
use Symfony\Component\Console\Input\ArrayInput;
class MyTest extends \PHPUnit_Framework_TestCase {
public function testComposer()
{
/** @var Application|\PHPUnit_Framework_MockObject_MockObject $composer */
$composer = $this->getMockForAbstractClass(Application::class);
$composer
->expects($this->any())
->method('run')
->will($this->returnValue(true));
$this->assertTrue(
$composer->run(new ArrayInput(['command' => 'install']))
);
}
}
这实际上运行代码:
$ bin/phpunit -c phpunit-fast.xml tests/MyTest.php
PHPUnit 4.8.10 by Sebastian Bergmann and contributors.
Runtime: PHP 5.6.13-1+deb.sury.org~trusty+3 with Xdebug 2.3.2
Configuration: phpunit-fast.xml
Loading composer repositories with package information
Installing dependencies (including require-dev) from lock file
Nothing to install or update
Generating autoload files
我尝试过各种
->getMock
(完全失败)和->getMockBuilder
的组合,但它似乎总是实际使用->run
方法,而不是存根。我想它是在某种程度上取代了内部的这些方法,但如果是这样的话,我如何防止它呢?
更新
有人问我为什么要使用
getMockForAbstractClass
而不仅仅是getMock
。当使用getMock
时,我得到以下输出:PHPUnit 4.8.10 by Sebastian Bergmann and contributors.
Runtime: PHP 5.6.13-1+deb.sury.org~trusty+3 with Xdebug 2.3.2
Configuration: phpunit.xml.dist
E
Time: 1.19 minutes, Memory: 4.50Mb
There was 1 error:
1) MyNamespace\MyTest::testComposer
PHPUnit_Framework_MockObject_RuntimeException: Cannot mock Symfony\Component\Console\Application::setDispatcher() because a class or interface used in the signature is not loaded
tests/MyTest.php:22
Caused by
ReflectionException: Class Symfony\Component\EventDispatcher\EventDispatcherInterface does not exist
tests/MyTest.php:22
FAILURES!
Tests: 1, Assertions: 0, Errors: 1.
尽管使用
$composer = new Application();
效果良好。事实上,如果我在测试上面加上那一行,它仍然声明一个class or interface
没有加载,尽管对象在前面被正确地实例化了。 最佳答案
我有3个解决方案:
一。添加事件调度器
将“symfony/event dispatcher”添加到您自己的require dev
"require-dev" : {
...
"symfony/event-dispatcher" : "^2.1"
}
通过校正试验:
<?php
/**
* MyTest.php
*/
namespace MyNamespace;
use Composer\Console\Application;
use Symfony\Component\Console\Input\ArrayInput;
class MyTest extends \PHPUnit_Framework_TestCase {
public function testComposer()
{
/** @var Application|\PHPUnit_Framework_MockObject_MockObject $composer */
$composer = $this->getMock(Application::class);
$composer
->expects($this->any())
->method('run')
->will($this->returnValue(true));
$this->assertTrue(
$composer->run(new ArrayInput(['command' => 'install']))
);
}
}
个人注意:这感觉像是一个肮脏的黑客,但迄今为止是最简单的解决方案
2.使用预言
与PHPUnt一起使用预言来模拟控制台。
"require-dev" : {
...
"phpspec/prophecy": "~1.0"
}
现在测试如下:
<?php
/**
* MyTest.php
*/
namespace MyNamespace;
use Composer\Console\Application;
use Prophecy\Prophet;
use Prophecy\Prophecy\ObjectProphecy;
use Symfony\Component\Console\Input\ArrayInput;
class MyTest extends \PHPUnit_Framework_TestCase {
public function testComposer()
{
$prophet = new Prophet();
$composerProphecy = $prophet->prophesize(Application::class);
$composerProphecy
->run(new ArrayInput(['command' => 'install']))
->willReturn(true);
/** @var Application $composer */
$composer = $composerProphecy->reveal();
$this->assertTrue(
$composer->run(new ArrayInput(['command' => 'install']))
);
}
}
个人注:我不喜欢告诉预言什么方法将被称为使用魔术方法,因为这些扰乱了我的IDE。
三。使用嘲弄
模拟系统的另一个选项。
"require-dev" : {
...
"mockery/mockery": "^0.9.4"
}
还有测试:
<?php
/**
* MyTest.php
*/
namespace MyNamespace;
use Composer\Console\Application;
use Symfony\Component\Console\Input\ArrayInput;
class MyTest extends \PHPUnit_Framework_TestCase {
public function testComposer()
{
/** @var Application|\Mockery\MockInterface $composer */
$composer = \Mockery::mock(Application::class);
$composer
->shouldReceive('run')
->with(ArrayInput::class)
->andReturn(true);
$this->assertTrue(
$composer->run(new ArrayInput(['command' => 'install']))
);
\Mockery::close();
}
}
个人注意:静态使用,必须记住清理,以及错误记录使用的变量在
shouldReceive
使我非常难过。四。(奖励)修复symfony控制台
似乎不太可能,但如果任何人都能解决如何修复#8200,那么这意味着没有人将不得不使用多个模拟框架(如果你已经使用PHPUnt无论如何)或添加脏黑客到他们需要的DEV为一个单独的测试。
关于php - PHPUnit中的Mock Composer实际上正在运行,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32975108/