Rat*_*tty 3 php phpunit unit-testing symfony
描述: 我有一个简单的类,它创建一个指向上传文件目录的符号链接,这些文件仅供注册会员使用。它使用当前用户的会话 ID 为用户生成随机目录。一旦用户注销,符号链接就会被删除。我想对类的功能进行单元测试。
问题: 由于大多数函数都是私有的,而且我认为没有任何理由将它们公开,我该如何正确地对此类进行单元测试?
这是 PHP 类的代码:
<?php
namespace Test\BackEnd\MemberBundle\Library;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\HttpKernel\KernelInterface;
class DirectoryProtector
{
/** @var SessionInterface $_session */
private $_session;
/** @var ContainerInterface $_kernel */
private $_kernel;
/**
* @param SessionInterface $session
* @param KernelInterface $kernel
*/
public function __construct( SessionInterface $session, KernelInterface $kernel )
{
$this->_session = $session;
$this->_kernel = $kernel;
}
/**
* @param bool|false $protect
* Public method to symlink directories
*/
public function protectDirectory($protect = FALSE)
{
if ($protect) {
if ( ! $this->doesDirectoryExists())
symlink($this->getAppDir() . '/uploads', $this->getViewableSessionDirectory());
} else {
if ($this->doesDirectoryExists())
unlink($this->getViewableSessionDirectory());
}
}
/**
* @return bool
* Check to see if viewable session directory exists or not
*/
private function doesDirectoryExists()
{
if (file_exists($this->getViewableSessionDirectory()))
return TRUE;
return FALSE;
}
/**
* @return string
* Get viewable session full directory path
*/
private function getViewableSessionDirectory()
{
return $this->getAppDir() . '/../web/files/' . $this->getSessionId();
}
/**
* @return string
* Return app root directory
*/
private function getAppDir()
{
return $this->_kernel->getRootDir();
}
/**
* @return string
* Return session id
*/
private function getSessionId()
{
return $this->_session->getId();
}
}
Run Code Online (Sandbox Code Playgroud)
这是当前测试类的代码:
<?php
namespace Test\BackEnd\MemberBundle\Tests\Library;
use Test\BackEnd\MemberBundle\Library\DirectoryProtector;
class DirectoryProtectorTest extends \PHPUnit_Framework_TestCase
{
public function testProtectDirectory()
{
//$this->markTestIncomplete("WIP on protect directory.");
$request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\SessionInterface')
->getMock();
$container = $this->getMockBuilder('Symfony\Component\HttpKernel\KernelInterface')
->getMock();
/** @var DirectoryProtector $dp */
$dp = $this->getMockBuilder('Test\BackEnd\MemberBundle\Library\DirectoryProtector')
->setConstructorArgs(array($request, $container))
->setMethods(array(
'getViewableSessionDirectory',
'getAppDir',
'getSessionId'
))
->getMock();
$dp->expects($this->once())
->method('doesDirectoryExists')
->will($this->returnValue(TRUE));
$dp->protectDirectory(TRUE);
}
}
Run Code Online (Sandbox Code Playgroud)
来自https://phpunit.de/manual/current/en/test-doubles.html
限制:final、private 和 static 方法
请注意,final、private 和 static 方法不能被存根或模拟。它们被 PHPUnit 的测试双重功能忽略并保留其原始行为。
对私有或受保护的方法进行单元测试不是一个好习惯。您应该测试公共API。私有方法应该通过 API 间接测试。也就是说,您可以使用反射使方法公开:
$instance = new DirectoryProtector(...);
$ref = new \ReflectionClass('DirectoryProtector');
$method = $ref->getMethod('doesDirectoryExists');
$method->setAccessible(true);
$this->assertTrue($method->invoke($instance));
Run Code Online (Sandbox Code Playgroud)