如何使用一种方法创建一个模拟类(不仅仅是一个模拟对象),实例化后会返回一个可预测的值?
在下面的代码中,我正在测试一个更大的概念(accounts-> preauthorize()),但我需要模拟对象Lookup,以便我可以为我的测试获得可预测的结果。
我正在使用PHPUnit和CakePHP,如果这很重要的话。这是我的情况:
// The system under test
class Accounts
{
public function preauthorize()
{
$obj = new Lookup();
$result = $obj->get();
echo $result; // expect to see 'abc'
// more work done here
}
}
// The test file, ideas borrowed from question [13389449][1]
class AccountsTest
{
$foo = $this->getMockBuilder('nonexistent')
->setMockClassName('Lookup')
->setMethods(array('get'))
->getMock();
// There is now a mock Lookup class with the method get()
// However, when my code creates an instance of Lookup and calls get(),
// it returns NULL. It should return 'abc' instead.
// I expected this to make my instances return 'abc', but it doesn't.
$foo->expects($this->any())
->method('get')
->will($this->returnValue('abc'));
// Now run the test on Accounts->preauthorize()
}
答案 0 :(得分:3)
这里有几个问题,但主要的一点是你在需要它的方法中实例化你的Lookup类。这使得无法模仿。您需要将Lookup实例传递给此方法以解除依赖关系。
class Accounts
{
public function preauthorize(Lookup $obj)
{
$result = $obj->get();
return $result; // You have to return something here, you can't test echo
}
}
现在你可以模拟Lookup。
class AccountsTest
{
$testLookup = $this->getMockBuilder('Lookup')
->getMock();
$testLookup->expects($this->any())
->method('get')
->will($this->returnValue('abc'));
$testAccounts = new Accounts();
$this->assertEquals($testAccounts->preauthorize($testLookup), 'abc');
}
不幸的是,我无法测试这个测试,但这应该让你朝着正确的方向前进。
显然,Lookup类的单元测试也应该存在。
您可能还会找到我的answer here。