doudun2565 2014-06-25 20:04
浏览 42

Php,克隆对象,添加新方法或覆盖它们

For testing purpose, I try to "fake" some objects. I want to do the following: I have an object, and want to add new methods, or overwrite some. Sadly, unlike in Java, its not possible to create "nameless" classes. Ok, I could do it by simply creating a new class, but I want to do it dinamicaly.

This is the class:

class Test
{
    public function method1()
    {
        return 'oldmethod1';
    }
    public function method2()
    {
        return 'oldmethod2';
    }
    public static function staticmethod1()
    {
        return 'staticmethod1';
    }
    public static function staticmethod2()
    {
        return 'staticmethod2';
    }
}

and now what I want to do:

$a = new Test();

$b = new CreateMockObjectFromObject($a);
$b->newmethod = function() { return 'newmethod'; };
$b->method2 = function() { return 'method2 is overwritten'; };
$b->staticmethod2 = function() { return 'staticmethod2 overwritten'; };

echo $b->method1().'<br>';
echo $b->method2().'<br>';
echo $b::staticmethod1().'<br>';
echo $b::staticmethod2().'<br>';

Here you can see my wishes: call a normal method, overwrite a method, call a static method, overwrite a method. The results: FAIL, SUCCESS, FAIL, FAIL.

I have a helper class:

class CreateMockObjectFromObject
{
    private $sourceObj;

    /**
     * @return
     */
    public function __call ($method, $args)
    {
        if (isset($this->sourceObj->$method))
        {
            return call_user_func_array($this->sourceObj->$method, $args);
        }

        if (isset($this->$method))
        {
            return call_user_func_array($this->$method, $args);
        }
        throw new Exception ($method.' NOT FOUND');
    }

    /**
     * @return
     */
    public static function __callStatic ($method, $args)
    {
        // I cant even imagine this...
    }

    /**
     * @return CreateMockObjectFromObject
     */
    public function __construct ($sourceObj)
    {
        $this->sourceObj = $sourceObj;
    }
}

I cant even imagine what about static methods. How to write this helper class so that all mocking/faking can work? And I didnt even talk about "const"-s... once again, I know it all could be done with extending, but I need to do in this way!

  • 写回答

1条回答 默认 最新

  • doumao1519 2014-06-26 19:51
    关注

    Mocking an entire class:

    $mock = Mockery::mock('FQ\ClassName');
    

    Mocking only certain methods:

    $mock = Mockery::mock('FQ\ClassName[method1, method2]')
    

    Here, method3, method4, ..., methodN will function exactly as they do in your class implementation.

    Making an expectation:

    $mock->shouldReceive('method1')
        ->once()
        ->andReturn('a value')
    ;
    

    After you make an expectation, then you Act upon the system under test:

    $return = $objectImTesting->performAction($mock);
    

    Once you act, you should assert that any return value is what it should be, given the input you provided:

    $this->assertEquals('a value', $return);
    

    Taking the above example, the test will fail if any of the following conditions are true:

    • method1 on your mock object is never called
    • method1 on your mock object is called more than once
    • the return value of performAction is not the literal value 'a value'

    Now, you've not reinvented the wheel and instead already gotten started writing tests. Also for free, you get everything that PHPUnit and Mockery provide you (how long do you think it would take you by yourself to be able to support Demeter Chains in your mocking framework?).

    Don't get me wrong, by all means go ahead and develop your testing framework if all you're interested in is learning. However, in my opinion I would not want to trust a testing framework that I developed by myself to ensure the code that I write works. I'd much rather use something that's open source and has been around for awhile so that I can sleep easier at night.

    More information:

    评论

报告相同问题?

悬赏问题

  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 CSAPPattacklab
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图
  • ¥15 关于大棚监测的pcb板设计
  • ¥15 stm32开发clion时遇到的编译问题
  • ¥15 lna设计 源简并电感型共源放大器
  • ¥15 如何用Labview在myRIO上做LCD显示?(语言-开发语言)
  • ¥15 Vue3地图和异步函数使用
  • ¥15 C++ yoloV5改写遇到的问题