首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何模拟你正在用Prophecy测试的类中的方法?

如何模拟你正在用Prophecy测试的类中的方法?
EN

Stack Overflow用户
提问于 2015-01-21 18:15:54
回答 3查看 6.2K关注 0票数 7

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

代码语言:javascript
复制
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,据我所知,它不允许你这样做:模仿魔法方法(EntityRepository_call),模仿不存在的方法,模仿你正在测试的类。如果这些都是真的,我就有点麻烦了,这意味着我不能在没有测试类中其他函数的情况下测试这个函数。

到目前为止,我的测试如下所示:

代码语言:javascript
复制
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和存储库上的承诺没有实现。如果我实例化我正在测试的类,测试会失败,因为函数会在同一个类上调用createUserFromLdap(),而这个类没有经过测试。

有什么建议吗?

EN

回答 3

Stack Overflow用户

发布于 2015-02-07 01:05:09

第一个问题:

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

“$em和存储库上的承诺没有实现”:

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

最后一点:

在揭示之前。

代码语言:javascript
复制
$service->createUserFromLdap()
   ->shouldBeCalled()
   ->willReturn(null);
票数 1
EN

Stack Overflow用户

发布于 2016-08-27 20:41:01

您试图实现的是一个部分模拟,这是Prophecy不支持的。更多信息请点击这里,https://github.com/phpspec/prophecy/issues/101https://github.com/phpspec/prophecy/issues/61

TL;DR;在设计你的类时要牢记单一的责任,这样你就不必模仿其他功能了。

票数 1
EN

Stack Overflow用户

发布于 2016-02-25 16:14:14

对于您无法模拟不存在的方法的问题,您可以使用

http://docs.mockery.io/en/latest/

而不是预言。Mockery允许您这样做。严格地说,这确实违反了一些好的设计规则,但另一方面,有时它是非常有用的。无论如何,就特性而言,mockery非常相似,而且它同样直观且易于使用imo。然而,他们仍然没有发布稳定的版本,所以如果你决定使用它,请注意这一点。

在这里您可以找到两个库的很好的比较

http://everzet.com/post/72910908762/conceptual-difference-between-mockery-and-prophecy

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28064601

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档