Php单元测试,带模拟的受保护方法

Php单元测试,带模拟的受保护方法,php,oop,unit-testing,mocking,tdd,Php,Oop,Unit Testing,Mocking,Tdd,我是TDD的新手。我被一些单元测试卡住了。。。请看一下我的代码。。。先谢谢你 class Parser{ protected function _checkCurlExistence() { // Unable to to mock function_exists, thats why fallback with this method return function_exists('curl_version'); } pu

我是TDD的新手。我被一些单元测试卡住了。。。请看一下我的代码。。。先谢谢你

class Parser{

    protected function _checkCurlExistence()
    {
        // Unable to to mock function_exists, thats why fallback with this method

        return function_exists('curl_version');
    }


    public function checkCurlExtension()
    {

        // I want to test 2 situations from this method...
        // 1. if curl extension exists
        // 2. or when curl extension does not exists...throw error

        if($this->_checkCurlExistence() === false){

            try{
                throw new CurlException(); //Some curl error handler exception class
            }catch(CurlException $error){
                exit($error->getCurlExtensionError());
            }

        }

        return true;
    }
}
要测试: 我的问题/要求: 你能填一下这些试卷吗。我像永远被困在这上面…无法继续我的TDD之旅

一些步骤(您可以跳过这些行): 我已经尽了最大的努力来解决这个问题,但我自己却无能为力。有些步骤是

我尝试了phpunit的本地mocky,padraic/mocky(git),codeception/aspect mock(git)来模拟两种情况下的checkcurlevision()方法。。。我不确定我是否做得对…这就是为什么,不张贴这些代码

我尝试了反射Api,通过魔术方法\u call()用方法重写类扩展。。。要将受保护方法动态转换为公共方法以帮助模拟


我也做了很多谷歌搜索。要知道,最好的做法是只测试公共方法。但是我的公共方法依赖于受保护的方法…所以我如何测试???

找到了一种通过

因此,我现在可以轻松地测试这两个场景

namespace 'myNameSpace';

class Parser{

    public function checkCurlExtension()
    {
        // I want to test 2 situations from this method...
        // 1. if curl extension exists
        // 2. or when curl extension does not exists...throw error

        if(function_exists('curl_version') === false){
            throw new CurlException(); //Some curl error handler exception class
        }

        return true;
    }


}

class ParserTest{

    private $parser;

    /**
    * @expectedException CurlException
    */
    public function testCheckCurlExtensionDoesNotExists()
    {
        $funcMocker = \PHPUnit_Extension_FunctionMocker::start($this, 'myNameSpace')
        ->mockFunction('function_exists')
        ->getMock();

        $funcMocker->expects($this->any())
        ->method('function_exists')            
        ->will($this->returnValue(false));

        $this->parser->checkCurlExtension(); 

    }

    public function testCheckCurlExtensionExists()
    {
       //we can do same here...please remember DRY...

    }
}

我更愿意通过checkCurlExtension()测试它,我的意思是如果找不到扩展,它会抛出异常。在测试用例中使用它。F.e$this->setExpectedException(“CurlException”);你就完了。这将在删除“exit()”函数之后进行。如果你想测试一个受保护的/私有的方法,你可以用一个公开这些方法的特殊测试类来扩展这个类?不应该测试受保护的/私有的方法。
namespace 'myNameSpace';

class Parser{

    public function checkCurlExtension()
    {
        // I want to test 2 situations from this method...
        // 1. if curl extension exists
        // 2. or when curl extension does not exists...throw error

        if(function_exists('curl_version') === false){
            throw new CurlException(); //Some curl error handler exception class
        }

        return true;
    }


}

class ParserTest{

    private $parser;

    /**
    * @expectedException CurlException
    */
    public function testCheckCurlExtensionDoesNotExists()
    {
        $funcMocker = \PHPUnit_Extension_FunctionMocker::start($this, 'myNameSpace')
        ->mockFunction('function_exists')
        ->getMock();

        $funcMocker->expects($this->any())
        ->method('function_exists')            
        ->will($this->returnValue(false));

        $this->parser->checkCurlExtension(); 

    }

    public function testCheckCurlExtensionExists()
    {
       //we can do same here...please remember DRY...

    }
}