Symfony2模拟类返回NULL

时间:2014-09-05 14:26:07

标签: php unit-testing symfony mocking

我遇到的问题是,当我尝试调用getSiteFromHostgetAlternateSiteFromHost方法时,存储库模拟类返回null。在创建模拟时我一定做错了,但我无法看到它。

你们可以发现什么吗?

以下是我正在测试的课程(服务):

class SiteHelper {
    private $container;
    private $em;
    private $request;

    public function __construct($entityManager, $container, $requestStack) {
        $this->em = $entityManager;
        $this->container = $container;
        $this->request = $requestStack->getCurrentRequest();
    }

    public function getCurrentSiteHost() {
        return $this->request->getHttpHost();
    }

    public function getCurrentSiteObj() {        
        $site = $this->em->getRepository('****')
                ->getSiteFromHost($this->getCurrentSiteHost());

        return $site[0];
    }

    public function getAlternateSiteObj() {
        $site = $this->em->getRepository('****')
                ->getAlternateSiteFromHost($this->getCurrentSiteHost());

        return $site;
    }
}

以下是测试类:

class SiteHelperTest extends \PHPUnit_Framework_TestCase {
    private $siteHelper;

    public function __construct() {
        $em = $this->buildMockEntityManager();
        $container = null;
        $requestStack = $this->buildMockRequestStack();

        $this->siteHelper = new SiteHelper($em, $container, $requestStack);
    }

    public function testCurrentSiteHost()
    {
        // assert that it's returning what it should be
        $this->assertEquals($this->siteHelper->getCurrentSiteHost(), '****');
    }

    public function testCurrentSiteObj()
    {        
        $this->assertEquals($this->siteHelper->getCurrentSiteObj()->getName(), '****');
    }

    public function testAlternateSiteObj()
    {
        $this->assertEquals($this->siteHelper->getAlternateSiteObj()->getName(), '****');
    }

    private function buildMockEntityManager() {
        $site = $this->getMock('\****\Bundle\MainBundle\Entity\Site');
        $site->expects($this->once())
            ->method('getName')
            ->will($this->returnValue('****'));

        $altSite = $this->getMock('\****\Bundle\MainBundle\Entity\Site');
        $altSite->expects($this->once())
            ->method('getName')
            ->will($this->returnValue('****'));

        $siteRepository = $this->getMockBuilder('\Doctrine\ORM\EntityRepository')
            ->disableOriginalConstructor()
            ->getMock();
        $siteRepository->expects($this->once())
            ->method('getSiteFromHost')
            ->will($this->returnValue(array(0 => $site)));
        $siteRepository->expects($this->once())
            ->method('getAlternateSiteFromHost')
            ->will($this->returnValue($altSite));

        $entityManager = $this->getMockBuilder('\Doctrine\Common\Persistence\ObjectManager')
            ->disableOriginalConstructor()
            ->getMock();
        $entityManager->expects($this->once())
            ->method('getRepository')
            ->will($this->returnValue($siteRepository));

        return $entityManager;
    }

    private function buildMockRequestStack() {
        $request = $this->getMockBuilder('\Symfony\Component\HttpFoundation\Request')
            ->disableOriginalConstructor()
            ->getMock();
        $request->expects($this->once())
            ->method('getHttpHost')
            ->will($this->returnValue('medicare.localhost'));

        $requestStack = $this->getMockBuilder('\Symfony\Component\HttpFoundation\RequestStack')
            ->disableOriginalConstructor()
            ->getMock();
        $requestStack->expects($this->once())
            ->method('getCurrentRequest')
            ->will($this->returnValue($request));

        return $requestStack;
    }
}

1 个答案:

答案 0 :(得分:1)

所以..我试着简化代码以更好地代表错误:

class TmpTest extends \PHPUnit_Framework_TestCase
{
    private $em;

    public function __construct()
    {
        $this->em = $this->buildMockEntityManager();
    }

    public function testCurrentSiteHost()
    {
        $this->assertEquals("pippo",
            $this->em->getRepository('\ACME\YourBundle\Entity\MyBetterCodedEntity')->getSiteFromHost()
        );
        $this->assertEquals(
        [0 => "pluto"],
            $this->em->getRepository('\ACME\YourBundle\Entity\MyBetterCodedEntity')->getAlternateSiteFromHost()
        );
    }

    private function buildMockEntityManager()
    {

        // Main bug was here, you have to mock the Class with the real methods, not the parent that doesn't has getSiteFromHost method (so it can't be mocked)
        $siteRepository = $this->getMockBuilder('\ACME\YourBundle\Repository\MyBetterCodedEntityRepository')
            ->disableOriginalConstructor()
            ->getMock();

        $siteRepository->expects($this->once())
            ->method('getSiteFromHost')
            ->will($this->returnValue("pippo"));

        $siteRepository->expects($this->once())
            ->method('getAlternateSiteFromHost')
            ->will($this->returnValue([0 => "pluto"]));

        $entityManager = $this->getMockBuilder('\Doctrine\Common\Persistence\ObjectManager')
            ->disableOriginalConstructor()
            ->getMock();

        // Exactly means that this will be called "2" times otherwise is an error.
        $entityManager->expects($this->exactly(2))
            ->method('getRepository')
            // you can define here the expected parameter
            //->with('\ACME\YourBundle\Entity\MyBetterCodedEntity')
            ->will($this->returnValue($siteRepository));

        return $entityManager;
    }

} 

嗯,这是测试的测试:)