如何在单元测试中使用ReflectionClass测试控制器的受保护方法?

时间:2018-08-02 01:34:42

标签: windows docker phpunit phalcon

环境

  • Windows10
  • 猎鹰3.2.4
  • 适用于Windows的Docker 18.03.1-ce-win65
  • phpunit 5.7.27

问题

我想使用带有phpunit的ReflectionClass测试控制器的私有属性,但是我没有设法检索数据。

使用ReflectionClass,我应该已经清除了访问权限的问题,但是我仍然收到null值。

我想解决此问题并正确完成单元测试。您看到我的代码出什么问题了吗?

测试

在上传excel文件的过程中,我想在尝试上传文件而不选择文件时测试错误内容。

错误消息

Call to a member function getValue() on null

代码

  • 测试文件
class StackOverFlowTest extends \UnitTestCase
{

    public function testsFileUploadError(){

        //StackOverFlowControllerのMockを作る
        $mockStackOverFlowController = $this->getMockBuilder(\App\Controllers\StackOverFlowController::class)
        ->setMethods(['runAction'])
        ->getMock();

        $mockStackOverFlowController->request = new class {

            public function hasFiles() 
            {
                return false;
            }
         };

            $reflectionClass = new \ReflectionClass('\Base\Controller');
         $reflectionClass->getMethod('_setErrorContent')->setAccessible(true);
            $reflectionClass->getMethod('_formatKey')->setAccessible(true);
            $reflectionClass->getMethod('_setContent')->setAccessible(true);
            $reflectionClass->getproperty('_content')->setAccessible(true);

            $mockStackOverFlowController->runAction(1,1);

            $content = $reflectionClass->getMethod('_setContent')->setAccessible(true)->getproperty('_content')->getValue();

            $this->assertEquals(
                "select file",
                $content->_content,
                "file select error"
            );
        }
    }
  • 实际正在移动的控制器(仅必要零件)
class StackOverflowController extends \Base\Controller
{

    public function runAction($firstId, $secondId)
    {
        // Check that file was uploaded.
        if (!$this->request->hasFiles()) {
            $this->_setErrorContent('Select file, 'snackbar');
        } else {
  • 扩展了BaseController。

在_setContent之后,转到afterExecuteRoute方法并将其传递到那里查看

class Controller extends \Phalcon\Mvc\Controller
{
    const ERRORS_RESPONSE_KEY = 'errors';
    protected $_content;

    protected function _setErrorContent($data, $key = null)
    {
        $key = $this->_formatKey($key);
        $this->_setContent($data, self::ERRORS_RESPONSE_KEY . $key);
    }

    private function _formatKey($key = null)
    {
        if (is_string($key) && !empty($key)) {
            return '.' . $key;
        } elseif (is_null($key)) {
            return '';
        }
        throw new \Exception('must specify response key', 500);
    }

    protected function _setContent($data, $keys)
    {
        $content = $this->_content;
        $temp = &$content;

        foreach (explode('.', $keys) as $key) {
            $temp = &$temp[$key];
        }

        $temp = is_array($temp) ? array_merge($temp, $data) : $data;
        $this->_content = $content;
    }

2 个答案:

答案 0 :(得分:0)

这仅表示没有此类属性,您确定要访问适当的属性吗?您不需要使用_content吗?我认为您不能使用反射来访问方法主体中的变量。

答案 1 :(得分:0)

这个问题由我自己解决了。 我可以得到私有财产!

$propGetter = Closure::bind(function ($prop) {
        return $this->$prop;
    }, $class, $class);
    return $propGetter;

$ class是类的模拟。