php - 如何模拟您正在使用 Prophecy 测试的类中的方法?

标签 php symfony phpunit prophecy

我想使用 Prophecy ("phpspec/prophecy-phpunit") 第一次为我的类(class)创建单元测试。我想测试一个调用同一服务中另一个函数的函数,代码如下:

class UserManager
{
    private $em;
    private $passwordHelper;

    public function __construct(\Doctrine\ORM\EntityManager $em, \MainBundle\Helper\PasswordHelper $passwordHelper)
     {
         $this->em = $em;
         $this->passwordHelper = $passwordHelper;
     }

     public function getUserForLdapLogin($ldapUser)
     {
          $dbUser = $this
              ->em
              ->getRepository('MainBundle:User')
              ->findOneBy(array('username' => $ldapUser->getUsername()));

         return (!$dbUser) ?
              $this->createUserFromLdap($ldapUser) :
              $this->updateUserFromLdap($ldapUser, $dbUser);
     }

我遇到的第一个问题是,我使用的是 findOneByUsername,据我所知,Prophecy 不允许您:模拟魔术方法(_call for EntityRepository), mock 不存在的方法,mock 你正在测试的类。如果这些都是真的,那我就有点头疼了,这意味着我不能在不测试类中其他函数的情况下测试这个函数。

到目前为止,我的测试是这样的:

class UserManagerTest extends \Prophecy\PhpUnit\ProphecyTestCase
{

      public function testGetUserForLdapLoginWithNoUser()
      {
          $ldapUser = new LdapUser();
          $ldapUser->setUsername('username');

          $em = $this->prophesize('Doctrine\ORM\EntityManager');
          $passwordHelper = $this->prophesize('MainBundle\Helper\PasswordHelper');

          $repository = $this->prophesize('Doctrine\ORM\EntityRepository');
          $em->getRepository('MainBundle:User')->willReturn($repository);
          $repository->findOneBy(array('username' => 'username'))->willReturn(null);

          $em->getRepository('MainBundle:User')->shouldBeCalled();
          $repository->findOneBy(array('username' => 'username'))->shouldBeCalled();

          $service = $this->prophesize('MainBundle\Helper\UserManager')
            ->willBeConstructedWith(array($em->reveal(), $passwordHelper->reveal()));

          $service->reveal();
          $service->getUserForLdapLogin($ldapUser);
     }
}

当然,测试失败是因为 $em 上的 promise 和存储库没有实现。如果我实例化我正在测试的类,测试将失败,因为该函数随后在同一类上调用 createUserFromLdap() 并且未经过测试。

有什么建议吗?

最佳答案

第一个问题:

不要使用魔法,魔法是邪恶的。 __call 可能会导致不可预知的行为。

“$em 上的 promise 和存储库未实现”:

不要让你的代码依赖于类,而是依赖于接口(interface)。 然后模拟 Interface 而不是 Class ! 您应该模拟 ObjectManager 而不是 EntityManager。 (不要忘记更改参数的类型)

最后一点:

揭示之前。

$service->createUserFromLdap()
   ->shouldBeCalled()
   ->willReturn(null);

关于php - 如何模拟您正在使用 Prophecy 测试的类中的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28064601/

相关文章:

php - Facebook邀请好友对话框高度问题

php - Assets / Twig : An exception has been thrown during the compilation of a template (Unable to find file)

phpunit - 如何在 Codeception 功能测试中使用 PHPUnit 断言方法?

PHPUnit教程?或者更通用的 - 值得推荐的单元测试教程?

php - 使用 PHPUnit 测试 Guzzle 调用时无法找到包装器

javascript - Uncaught ReferenceError : function is not defined

php - 上传的 csv 不起作用

php - Google People API(如何使用 API key 进行身份验证)

php - Symfony 进程组件 - 设置命令的输入参数

symfony - 如何在Symfony 4中正确声明类?