doulun1939 2017-06-05 11:04
浏览 13
已采纳

模拟在方法中间创建的对象

I know that creating an instance of a Class in the middle of a method it's a bad practice since it makes code hard to test. But I can't refactor the code, so I need to find a way to mock an Object created with new in the middle of a method under test.

Used Frameworks: PHPUnit, Mockery, WP_Mock

Example: Here I need to mock the get_second_string() method from the instance of the class ExternalClass

Class MyClass {

    function methodUnderTest($string) {
        $objToMock = new ExternalClass();
        $second_string = $objToMock->get_second_string();
        $final_string = $string . $second_string;
        return $final_string;
    }
}
Class TestMyClass extends PHPUnit_Framework_TestCase {
    public function setUp() {
    }
    public function tearDown() {
    }

    public function test_methodUnderTest() {
        $externalObject = $this->getMockBuilder('ExternalClass')
                               ->setMethods(['get_second_string'])
                               ->getMock;
        $externalObject->expects($this->once())
                       ->method('get_second_string')
                       ->willReturn(' two');
        $testObj = new MyClass();
        $this->assertEquals('one two', $testObj->methodUnderTest('one');
    }
}
  • 写回答

3条回答 默认 最新

  • dongmei8760 2017-06-07 08:01
    关注

    If you really have no opportunity to refactor the code or do some appropriate integration testing, you might want to take a look at https://github.com/php-test-helpers/php-test-helpers#intercepting-object-creation and https://github.com/krakjoe/uopz/tree/PHP5

    Still I think the code you make would profit a lot more from refactoring than monkey patching.

    Besides, the refactoring does not need to be very heavy. You might do at least this:

    class MyClass
    {
        private $externalsFactory;
    
        public function __construct($externalsFactory){
            $this->externalsFactory = $externalsFactory;
        }
    
        public function methodUnderTest($str){
            $external = $this->externalsFactory->make();
            $second_string = $external->get_second_string();
            $finalString = $str.$second_string;
            return $finalString;
        }
    }
    
    class ExternalsFactory
    {
        public function make(){
            return new ExternalClass();
        }
    }
    
    class ExternalClass
    {
        public function get_second_string(){
            return 'some real stuff may be even from database or whatever else it could be';
        }
    }
    
    class MyClassTest extends PHPUnit_Framework_TestCase
    {
        private $factoryMock;
        private $myClass;
    
        public function setUp(){
            $this->factoryMock = $this->getMockBuilder('ExternalsFactory')
                                      ->getMock();
            $this->myClass = new MyClass($this->factoryMock);
        }
    
        public function testMethodUnderTest(){
            $extenalMock = $this->createMock('ExternalClass');
            $extenalMock->method('get_second_string')
                        ->willReturn('second');
            $this->factoryMock->method('make')
                              ->willReturn($extenalMock);
            $this->assertSame('first-and-second', $this->myClass->methodUnderTest('first-and-'));
        }
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 表达式必须是可修改的左值
  • ¥15 如何绘制动力学系统的相图
  • ¥15 对接wps接口实现获取元数据
  • ¥20 给自己本科IT专业毕业的妹m找个实习工作
  • ¥15 用友U8:向一个无法连接的网络尝试了一个套接字操作,如何解决?
  • ¥30 我的代码按理说完成了模型的搭建、训练、验证测试等工作(标签-网络|关键词-变化检测)
  • ¥50 mac mini外接显示器 画质字体模糊
  • ¥15 TLS1.2协议通信解密
  • ¥40 图书信息管理系统程序编写
  • ¥20 Qcustomplot缩小曲线形状问题