2015-01-21 45 views
5

我想第一次使用Prophecy(「phpspec/prophecy-phpunit」)爲我的課程創建單元測試。我想測試調用同一服務其他功能的功能,下面的代碼:如何從預測的類中模擬一個方法?

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和預言,據我所知去,不允許你到:模擬魔法方法(_callEntityRepository),不存在的模擬方法,模擬您正在測試的類。如果這些都是真的,我就有點尷尬,這意味着我無法測試此功能,而無需測試課程中的其他功能。

到目前爲止,我的測試是這樣的:

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的承諾,和倉庫都沒有履行。如果我實例化了正在測試的類,則測試失敗,因爲該函數然後在同一個類上調用並且未經測試。

有什麼建議嗎?

+0

我從來沒有用過它,所以不能自己幫忙。但是,如果你仍然在幾天之內陷入困境(即可以應用問題賞金),請使用@halfer ping我,然後添加一個。好問題! – halfer 2015-01-21 14:50:51

+0

最佳答案我發現到目前爲止,您的班級可能不遵循S.O.L.I.D原則,並且沒有單獨的責任。因此,在嘗試使用預言之前,請讓你的課程順利進行。 – anegrea 2015-01-22 15:55:31

回答

0

第一個問題:

不要使用魔法,魔法是邪惡的。 __call可能會導致不可預知的行爲。

「上$ EM的承諾,和庫不符合」:

不要讓你的代碼依賴於類,但接口。 然後模擬界面而不是類! 你應該模擬ObjectManager而不是EntityManager。 (不要忘記設置參數的類型)

而且最後一點:

之前透露。

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

關於你不能夠嘲笑不存在的方法的問題,你可以在預言代替使用

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

。嘲笑允許你這樣做。嚴格地說,這確實破壞了一些優秀設計的規則,但另一方面,有時候它非常有用。無論如何,嘲諷與功能一樣非常相似,並且它同樣直觀且易於使用imo。但是,他們仍然沒有發佈穩定版本,所以如果您決定使用它,請注意這一點。

在這裏,你可以找到兩個庫

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

相關問題