具有依赖注入的同一类的Mock方法 - PHP

时间:2014-02-21 16:11:21

标签: php unit-testing mocking

我想知道如何在同一个类上模拟一个方法,这个类本身就有依赖。

我们举一个例子:

Class SomeClassA {

  protected $dependency;

  function __construct(Dependency $dependency) {

     $this->dependency = $dependency;

  }


  public function methodToTest() {

         if ( !is_null( $this->methodCalled() ) )

            return $this->methodCalled();

         else

            return "it\'s not ok!"

         // need to test this method mocking the methodCalled()

  }


  public function methodCalled($message) {

        return $message;

  }


}

如果这个类没有依赖关系,我可以这样做:

public function test_methodToTest() {

    $this->getMock('SomeClassA',['methodCalled'])
         ->with('message')
         ->expects($this->once())
         ->will($this->returnValue('message'));

   $someClassA = new SomeClassA();

   $this->assertEquals('message',$someClassA->methodToTest('message'));


}

修改

让我们说这个例子来改善我的问题的含义我只是改变了前面的例子:

Class SomeClassA {

  protected $dependency;

  function __construct(Dependency $dependency) {

     $this->dependency = $dependency;

  }


  public function methodToTest() {

         if ( $this->methodCalled() ) // i was wondering how mock this method

            return $this->dependency->someDependencyMethod(); // not this

         else

            return "it\'s not ok!"



  }


  public function methodCalled() {

        return true;

  }


}

我只是不明白如何模仿方法$this->methodClass()。我发现很难,因为SomeClassA类有一个依赖。而我正在测试该类的方法。

2 个答案:

答案 0 :(得分:3)

你将通过单元测试做很多事情:

  • 模仿依赖。
  • 设定对依赖的期望。
  • 将模拟的依赖项注入真实的非模拟对象。

为了展示一个真实的例子,您的依赖项需要实际使用(它不在您的示例代码中,我认为您的代码可能会被破坏)。因此,我们将您的methodToTest类更改为此示例:

public function methodToTest(){       return $ dependency-> returnValue();   }

所以现在你的methodToTest会返回从dependeency获得的值。为了测试这个,让我们模拟一个依赖:

$dep = $this->getMock('Dependency');

然后让我们设定期望及其回报:

$dep->expects($this->once())
     ->method('returnValue')
     ->will($this->returnArgument('hello world'));

这里我们说依赖项期望returnValue被调用一次并返回字符串'hello world'。

现在让我们测试一下实际的类:

$tester = new SomeClassA($dep);

请注意,我们将模拟依赖项注入真实的SomeClassA

$this->assertEquals('hello world',$tester->methodToTest());

这个断言是唯一的'可见'断言。它确保methodToTest返回依赖项中的值。测试还将确保依赖项上的'returnValue'函数只调用一次。

答案 1 :(得分:2)

您可以执行以下操作:

class SomeClassATest {
    public function testMethodToTest() {
        $someClassA = $this->getMockBuilder('SomeClassA')
            ->setMethods(array('methodCalled'))
            ->getMock();
        $someClassA->expects($this->once())
            ->method('methodCalled')
            ->will($this->returnValue('your mocked value here'));
        $actual = $someClassA->methodToTest();
        $this->assertEquals('your expectation here', $actual);
    }
}

这仅在methodCalled是公共的或受保护的情况下才有效,因为您只能模拟公共和受保护的方法。它的工作方式是测试$someClassASomeClassA的模拟实例,其中只有methodCalled被替换为您的测试行为,其他所有内容都保持不变。