我想知道如何在同一个类上模拟一个方法,这个类本身就有依赖。
我们举一个例子:
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类有一个依赖。而我正在测试该类的方法。
答案 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
是公共的或受保护的情况下才有效,因为您只能模拟公共和受保护的方法。它的工作方式是测试$someClassA
,SomeClassA
的模拟实例,其中只有methodCalled
被替换为您的测试行为,其他所有内容都保持不变。