使用新关键字insight对PHP类进行单元测试
所以前几天我设计了一个糟糕的PHP类,例如,它填充了一些对象:使用新关键字insight对PHP类进行单元测试,php,unit-testing,class,mocking,phpunit,Php,Unit Testing,Class,Mocking,Phpunit,所以前几天我设计了一个糟糕的PHP类,例如,它填充了一些对象: class Populator { function populate(array $data): array { $result = []; foreach ($data as $row) { $result[] = new PopulateMeGently($row); } return $result; } }
class Populator
{
function populate(array $data): array
{
$result = [];
foreach ($data as $row) {
$result[] = new PopulateMeGently($row);
}
return $result;
}
}
同样假设populateMegenly
真的很重,唯一的选择是在单元测试中模拟它
那么如何在Populator
类中测试populate
方法呢?或者如何重构它,使其可测试?
我有可用的IoC和其他花哨的东西可以用,但现在我试过的东西都显得笨重难看
谢谢大家! 你能做的最省钱的事情就是像这样
class Populator
{
private $rowProcessor;
public function __construct($rowProcessor){
$this->rowProcessor = $rowProcessor;
}
public function populate(array $data){
$result = [];
foreach($data as $row){
$result[] = $this->rowProcessor->process($row);
}
return $result;
}
}
一般的想法是将一些其他对象注入到Populator
中,并使其负责populateMegence
的创建。不要new
在内部,因为它无法控制,因此不稳定
关于名称和实现,它可能是一些工厂
,甚至可以实现类似makeDefault()
,makenullpopulatemegenly()
,makeFromRaws($data)
或任何适合您的设计和需要的方法
不,您可以将内容模拟为:
class PopulatorTest extends PHPUnit_Framework_TestCase
{
private $populator;
private $rowProcessorMock;
public function setUp(){
$this->rowProcessorMock = $this->getMockBuilder('RowProcessor')
->setMethods(array('process'))
->getMock();
$this->populator = new Populator($this->rowProcessorMock);
}
/**
* @test
*/
public function canPopulate(){
$data = array(0, 1);
$this->rowProcessorMock->expects($this->exactly(2))
->method('process')
->withConsecutive(
[$this->equalTo(0)],
[$this->equalTo(1)]
)
->will($this->onConsecutiveCalls('zero', 'one'));
$result = $this->populator->populate($data);
$this->assertSame(array('zero', 'one'), $result);
}
}
canPopulate
测试需要使用$data
进行的所有操作——所有项目都按顺序处理,结果作为转换数据数组返回。请注意,您实际上不需要模仿PopulateMegeny
(或者您将其重命名为的任何名称)。您只需确保负责处理数据的对象使用适当的参数调用,并正确返回其结果。是否填充要测试的类?您正在测试一个调用populate方法的方法吗?是的,我现在使用工厂,但不知道是否还有其他更优雅的方法。重点不是使用/不使用工厂,而是将依赖项推出类之外。为了使Populator
可测试,您必须打破Populator
对populateMegency