2015-01-21 14 views
5

Tôi muốn sử dụng Prophecy ("phpspec/prophecy-phpunit") lần đầu tiên để tạo các bài kiểm tra đơn vị cho các lớp học của tôi. Tôi muốn thử nghiệm một chức năng mà các cuộc gọi một chức năng trong cùng một dịch vụ, đây là các mã:Làm thế nào để thử một phương thức từ lớp bạn đang thử nghiệm với lời tiên tri?

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); 
    } 

Vấn đề đầu tiên tôi đã được rằng tôi đã sử dụng findOneByUsername và Lời tiên tri, theo như hiểu biết của tôi đi, không cho phép bạn để: phương pháp ma thuật giả (_call cho EntityRepository), phương pháp giả không tồn tại, giả lập lớp bạn đang thử nghiệm. Nếu đây là sự thật tôi đang ở trong một chút của dưa chua, có nghĩa là tôi không thể kiểm tra chức năng này mà không kiểm tra các chức năng khác trong lớp.

Cho đến nay, thử nghiệm của tôi trông như thế này:

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); 
    } 
} 

Và tất nhiên, các cuộc thử nghiệm thất bại vì những lời hứa trên $em, và kho lưu trữ không được đáp ứng. Nếu tôi khởi tạo lớp tôi đang kiểm tra, các bài kiểm tra thất bại vì hàm này sau đó gọi trên cùng một lớp và không được kiểm tra.

Mọi đề xuất?

+0

Tôi chưa bao giờ sử dụng nó, vì vậy tôi không thể giúp tôi.Tuy nhiên, nếu bạn vẫn bị kẹt trong một vài ngày (ví dụ: khi tiền thưởng câu hỏi có thể được áp dụng), hãy ping tôi bằng @halfer và tôi sẽ thêm một tài khoản. Câu hỏi hay! – halfer

+0

Câu trả lời hay nhất tôi đã tìm thấy cho đến nay là lớp học của bạn có thể không tuân thủ các nguyên tắc S.O.L.I.D và không có trách nhiệm nào. Vì vậy, có được lớp học của bạn ngay trước khi bạn cố gắng sử dụng lời tiên tri. – anegrea

Trả lời

0

Vấn đề đầu tiên:

Không sử dụng phép thuật, ma thuật là điều xấu. __call có thể dẫn đến hành vi không thể đoán trước.

"những lời hứa trên $ em, và kho lưu trữ không được trọn":

Đừng làm cho mã của bạn phụ thuộc vào lớp nhưng Interface. Sau đó, giả lập Giao diện thay vì Lớp! Bạn nên giả lập ObjectManager thay vì EntityManager. (đừng quên thay đổi loại thông số của bạn)

Và điểm cuối cùng:

Trước khi tiết lộ.

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

Về vấn đề của bạn không có khả năng để thử phương pháp đó không tồn tại, bạn có thể sử dụng

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

thay cho lời tiên tri. Mockery cho phép bạn làm điều đó. Nói đúng ra, điều đó phá vỡ một số quy tắc của thiết kế tốt, nhưng mặt khác, đôi khi nó chỉ rất hữu ích. Dù sao thì, việc nhạo báng rất giống nhau, theo như tính năng đi, và nó cũng giống như trực quan và dễ sử dụng. Tuy nhiên, họ vẫn chưa phát hành phiên bản ổn định, vì vậy chỉ cần nhận thức được rằng nếu bạn quyết định sử dụng nó.

Ở đây bạn có thể tìm thấy một sự so sánh tốt đẹp của hai thư viện

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

Các vấn đề liên quan