我正在尝试开始使用 PHPSpec,但我碰壁了。为了在我被赋予使用的现有代码中模拟正确的东西,事情变得有点复杂,但本质上我的问题涉及测试在刚刚创建的对象上发生的事情。
我有RepositoryFactory
一个createRepository(EntityManager $em, $entityName)
DoctrineEntityManager::getRepository($entityName)
只是调用RepositoryFactory::getRepository(EntityManager $em, $entityName)
,如果存储库不存在,那调用RepositoryFactory::createRepository(EntityManager $em, $entityName)
因此,在我的测试中,存储库是从RepositoryFactory::getRepository
.
class MyEntityManagerSpec extends ObjectBehavior
{
function let(..., MyRepositoryFactory $rfact, MyEntityRepository $repo, ...)
{
....
$rfact->getRepository(Argument::any(), Argument::any())
->willReturn($repo);
...
}
function it_sets_a_field_on_repositories(MyEntityRepository $repo)
{
//This class calls its own getRepository, which calls
//getRepository on the factory, which ->willReturn($repo).
//So, effectively (but without mocking the SUT) that means
//$this->getRepository($entityName)->willReturn($repo)
$entityName = 'blah\blah\FakeEntity';
$repo->setField(Argument::any())->shouldBeCalled();
//The above fails with
//"No calls that match MyEntityRepository\P112->setField(*)"
$gotRepo = $this->getRepository($entityName);
$repo->setField(Argument::any())->shouldHaveBeenCalled();
//This fails in the same way
$gotRepo->shouldBe($repo);
//This test passes but doesn't let me verify the property was set
//and is therefore of little help to me
$gotRepo->getField()->shouldNotBeNull();
//I wanted to use shouldBe/shouldHaveBeenCalled but if the field's
//been set that's just as good. Except this fails as well, with
//"is_null(null) not expected to return true, but it did."
}
现在,在孤立测试的答案开始出现之前,我意识到了这一点。我首先开始尝试编写对字段设置的检查,MyRepositoryFactory::createRepository
但出现了同样的问题——如果我在 中制作对象createRepository
,那么我没有可以使用 shouldBe/shouldHaveBeenCalled 进行测试的模拟。但是我正在尝试在这里做正确的事情,所以如果这是我测试的错误地方,我宁愿重构很多而不是通过一个hacky测试。
编辑:这是正在测试的实际位
class MyEntityManager
{
...
public function getRepository($entityName)
{
$repo = parent::getRepository($entityName);
$metaData = $this->getClassMetadata($entityName);
$flag = $this->getTarget() && $metaData->reflClass
->implementsInterface('Caj\Bundle\NameOfBundle\Model\NameOfBundleInterface');
if($flag) {
$repo->setField($this->getField());
}
return $repo;
}
}
上面的 $repo 应该在这里被嘲笑;parent::getRepository
==> RepositoryFactory::getRepository
==>RepositoryFactory::createRepository
此外,我知道测试进入了if($flag)
块,但里面的代码不起作用。$this->getField()
正常工作并返回,但$repo->setField
仍收到 null。$repo->setField($field)
是一个没有时髦逻辑的普通二传手。