代码之家  ›  专栏  ›  技术社区  ›  Nathan MacInnes

支持链接方法的模拟对象

  •  7
  • Nathan MacInnes  · 技术社区  · 14 年前

    我想知道是否有一种相当简洁的方法来模拟支持方法链接的对象。。。因此,例如,数据库查询对象可能具有如下所示的方法调用:

    $result = $database->select('my_table')->where(array('my_field'=>'a_value'))->limit(1)->execute();
    

    如果我必须模拟两个不同的select查询,以便它们返回不同的结果,问题就来了。有什么想法吗?

    这是关于PHPUnit的,但是来自其他单元测试框架的经验将有所帮助。

    3 回复  |  直到 14 年前
        1
  •  14
  •   Gordon Haim Evgi    14 年前

    我不确定这是你要找的,所以请留言:

    class StubTest extends PHPUnit_Framework_TestCase
    {
        public function testChainingStub()
        {
            // Creating the stub with the methods to be called
            $stub = $this->getMock('Zend_Db_Select', array(
                'select', 'where', 'limit', 'execute'
            ), array(), '', FALSE);
    
            // telling the stub to return a certain result on execute
            $stub->expects($this->any())
                 ->method('execute')
                 ->will($this->returnValue('expected result'));
    
            // telling the stub to return itself on any other calls
            $stub->expects($this->any())
                 ->method($this->anything())
                 ->will($this->returnValue($stub));
    
            // testing that we can chain the stub
            $this->assertSame(
                'expected result',
                $stub->select('my_table')
                     ->where(array('my_field'=>'a_value'))
                     ->limit(1)
                     ->execute()
            );
        }
    }
    

    您可以将此与期望结合起来:

    class StubTest extends PHPUnit_Framework_TestCase
    {
        public function testChainingStub()
        {
            // Creating the stub with the methods to be called
            $stub = $this->getMock('Zend_Db_Select', array(
                'select', 'where', 'limit', 'execute'
            ), array(), '', FALSE);
    
            // overwriting stub to return something when execute is called
            $stub->expects($this->exactly(1))
                 ->method('execute')
                 ->will($this->returnValue('expected result'));
    
            $stub->expects($this->exactly(1))
                 ->method('limit')
                 ->with($this->equalTo(1))
                 ->will($this->returnValue($stub));
    
            $stub->expects($this->exactly(1))
                 ->method('where')
                 ->with($this->equalTo(array('my_field'=>'a_value')))
                 ->will($this->returnValue($stub));
    
            $stub->expects($this->exactly(1))
                 ->method('select')
                 ->with($this->equalTo('my_table'))
                 ->will($this->returnValue($stub));
    
            // testing that we can chain the stub
            $this->assertSame(
                'expected result',
                $stub->select('my_table')
                     ->where(array('my_field'=>'a_value'))
                     ->limit(1)
                     ->execute()
            );
        }
    }
    
        2
  •  1
  •   D_R    10 年前

    我知道这是个老问题,但它可能对未来的谷歌有更多帮助。

    我在寻找一个框架时也遇到了问题,该框架将为模拟stubbing方法链接提供简单易用的语法。然后我决定编写一个简单易用的模拟库。

    用法示例:

     // Creating a new mock for SimpleClassForMocking
     $mock = ShortifyPunit::mock('SimpleClassForMocking');
    
      ShortifyPunit::when($mock)->first_method()
                                ->second_method(2,3)->returns(1);
    
      ShortifyPunit::when($mock)->first_method()
                                ->second_method(2,3,4)->returns(2);
    
      ShortifyPunit::when($mock)->first_method(1)
                                ->second_method(2,3,4)->returns(3);
    
      ShortifyPunit::when($mock)->first_method(1,2,3)
                                ->second_method(1,2)->third_method()->returns(4);
    
      $mock->first_method()->second_method(2,3); // returns 1
      $mock->first_method()->second_method(2,3,4); // returns 2
      $mock->first_method(1)->second_method(2,3,4); // returns 3
      $mock->first_method(1,2,3)->second_method(1,2)->third_method(); // return 4
    

    github:

    https://github.com/danrevah/ShortifyPunit#stubbing-method-chanining

        3
  •  0
  •   d11wtq Vadim Baryshev    14 年前

    这可能不是您要寻找的答案,但我在几年前编写了一个模拟对象框架,它将处理这种“取决于输入”断言:

    http://code.google.com/p/yaymock/

    http://code.google.com/p/yaymock/wiki/Expectations

    我写它是为了在支持Swift Mailer的单元测试中使用,但它并没有被任何其他项目(我知道的)广泛采用。其目的是提供比PHPUnit和SimpleTest更好的对模拟对象调用的控制和内省。