我正在构建一个需要直接访问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();
的方法可以正常工作,但事实上,如果我在测试代码之前添加这一行,它仍然声称未加载类或接口
,尽管对象早期已经正确实例化。
Application
类作曲家不是一个抽象类。那你为什么要使用getMockForAbstractClass()
呢? - Sven::class
是正确的,也更加优雅。现在的问题是:你为什么缺少那个接口?你是否查看了安装的依赖项并进行了搜索?它是否存在?我获取模拟对象的常规步骤是$this->getMockBuilder(Any::class)->disableOriginalConstructor()->getMock()
,因为获取模拟对象不应该执行任何操作。这很繁琐,这就是我更喜欢使用 Mockery 或 Prophecy 的原因。 - Sven