duanlan3598 2015-08-10 23:37
浏览 192

使用私有方法正确测试一个简单的类

Description: I have a simple class that creates a symlink to a directory of uploaded files that are only available to registered members. It uses the current users session id in order to generate the random directory for the user. Once the user logs out, the symlink is removed. I would like to unit test the functionality of the class.

Question: How do I go about properly unit testing this class since most functions are private, and I don't see any reason to make them public?

Here is the code for the PHP class:

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

}

Here is the code for the current test class:

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

}

}
  • 写回答

2条回答 默认 最新

  • drs3925 2015-08-11 00:54
    关注

    From https://phpunit.de/manual/current/en/test-doubles.html

    Limitation: final, private, and static methods

    Please note that final, private and static methods cannot be stubbed or mocked. They are ignored by PHPUnit's test double functionality and retain their original behavior.

    Is not a good practice to unit test private or protected methods. You should test the public API. Private methods are supposed to be tested indirectly through the API. That said, you can make the method public with reflection:

    $instance = new DirectoryProtector(...);
    
    $ref = new \ReflectionClass('DirectoryProtector');
    
    $method = $ref->getMethod('doesDirectoryExists');
    $method->setAccessible(true);
    
    $this->assertTrue($method->invoke($instance));
    
    评论

报告相同问题?

悬赏问题

  • ¥15 下图接收小电路,谁知道原理
  • ¥15 装 pytorch 的时候出了好多问题,遇到这种情况怎么处理?
  • ¥20 IOS游览器某宝手机网页版自动立即购买JavaScript脚本
  • ¥15 手机接入宽带网线,如何释放宽带全部速度
  • ¥30 关于#r语言#的问题:如何对R语言中mfgarch包中构建的garch-midas模型进行样本内长期波动率预测和样本外长期波动率预测
  • ¥15 ETLCloud 处理json多层级问题
  • ¥15 matlab中使用gurobi时报错
  • ¥15 这个主板怎么能扩出一两个sata口
  • ¥15 不是,这到底错哪儿了😭
  • ¥15 2020长安杯与连接网探