创建一个模拟类,其方法实例化时
问题描述:
我怎样才能创建一个模拟类(不只是一个模拟对象)返回值,条件是,当实例化将返回一个可预测值的方法?在下面的代码中,我测试了一个更大的概念(accounts-> preauthorize()),但我需要模拟对象查找,以便我可以获得可预测的结果以供测试使用。创建一个模拟类,其方法实例化时
我使用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()
}
答
这里有几个问题,但主要的问题是你在需要它的方法中实例化你的Lookup类。这使得它不可能嘲笑。您需要将查找实例传递给此方法以解耦依赖项。
class Accounts
{
public function preauthorize(Lookup $obj)
{
$result = $obj->get();
return $result; // You have to return something here, you can't test echo
}
}
现在你可以模拟查找。
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。
我简化了我的情况,使其更有意义。原来我简化了它。你为我简化的例子提供了一个合理的解决方案,所以谢谢。但事实上,preauthorize()是一个CakePHP控制器,其参数来自客户端,不能容纳HttpSocket实例。 (我改名为“Lookup”的实际上是CakePHP实用程序HttpSocket)。哎呀。谢谢,不过。 –
我从未使用过的蛋糕,但我听说它不是太好,只要现代的框架去。我会强调,不能孤立你的类来单元测试它们是一种代码味道。很明显,我无法判断这些异味来自您的代码还是来自您的框架。就我个人而言,我会花很长时间仔细研究我的架构。但是,我是一个单独的开发人员,没有人告诉我如何编写代码或使用什么框架。祝你好运。 – vascowhite
重新阅读您的评论。在我遇到的所有框架中,单元测试控制器是不可能的,它不能与它的依赖隔离。我通过将尽可能多的逻辑移出控制器并进入模型或服务层来克服这一点,以便我的控制器尽可能地瘦。如果你还没有这样做,这可能是你想要考虑的一种策略。 – vascowhite