我也想知道这就是我发现你的问题的方式。最后我决定做一些有点脏的事情......使用反射。
这是我要测试的方法:
/**
* ArrayPool constructor.
* @param array $tasks Things that might be tasks
*/
public function __construct(array $tasks)
{
foreach ($tasks as $name => $parameters) {
if ($parameters instanceof TaskInterface) {
$this->addTask($parameters);
continue;
}
if ($parameters instanceof DescriptionInterface) {
$this->addTask(new Task($parameters));
continue;
}
$this->addPotentialTask($name, $parameters);
}
}
出于此测试的目的,我不想实际运行->addTask
or ->addPotentialTask
,只知道它们会被调用。
这是测试:
/**
* @test
* @covers ::__construct
* @uses \Foundry\Masonry\Core\Task::__construct
*/
public function testConstruct()
{
$task = $this->getMockForAbstractClass(TaskInterface::class);
$description = $this->getMockForAbstractClass(DescriptionInterface::class);
$namedTask = 'someTask';
$parameters = [];
$arrayPool =
$this
->getMockBuilder(ArrayPool::class)
->disableOriginalConstructor()
->setMethods(['addTask', 'addPotentialTask'])
->getMock();
$arrayPool
->expects($this->at(0))
->method('addTask')
->with($task);
$arrayPool
->expects($this->at(1))
->method('addTask')
->with($this->isInstanceOf(TaskInterface::class));
$arrayPool
->expects($this->at(2))
->method('addPotentialTask')
->with($namedTask, $parameters);
$construct = $this->getObjectMethod($arrayPool, '__construct');
$construct([
0=>$task,
1=>$description,
$namedTask => $parameters
]);
}
神奇的是,getObjectMethod
它接受一个对象并返回一个可调用的闭包,该闭包将调用对象实例上的方法:
/**
* Gets returns a proxy for any method of an object, regardless of scope
* @param object $object Any object
* @param string $methodName The name of the method you want to proxy
* @return \Closure
*/
protected function getObjectMethod($object, $methodName)
{
if (!is_object($object)) {
throw new \InvalidArgumentException('Can not get method of non object');
}
$reflectionMethod = new \ReflectionMethod($object, $methodName);
$reflectionMethod->setAccessible(true);
return function () use ($object, $reflectionMethod) {
return $reflectionMethod->invokeArgs($object, func_get_args());
};
}
而且我知道循环和条件都可以正常运行,而无需进入我不想在此处输入的代码。

TL;博士:
- 禁用
__construct
- 设置模拟
__construct
对象实例化后使用反射调用
- 尽量不要为此失眠