将以下代码视为PHP样式的伪代码,以便了解我的观点。
class C extends PHPUnit_Framework_TestCase
{
public function m1()
{
$v = $this->m2();
if($v == "x")
{
throw new Exception();
}
}
protected function m2()
{
[...];
return $v;
}
}
现在我想添加一个测试,如果m2()返回“x”,则断言抛出异常。
我该如何模拟?
我考虑过在运行时使用Reflection重新定义方法,但似乎Reflection没有提供这样的功能,我不得不求助于像classkit或runkit这样的实验性扩展。这会是要走的路吗?
在这种情况下,我可以扩展类并重新定义m2(),但是我会在哪里放置该派生类?在与测试相同的文件中?
如果我选择m2为私有,后一种解决方案将不再适用。
我很确定最好的做法是处理这种情况。
答案 0 :(得分:4)
以太我完全不关心你在这里做什么,或者你做的事情让我很困惑。
对我而言,似乎您要求检查您的测试方法是否会引发异常。
C类扩展了PHPUnit_Framework_TestCase
为什么要测试您的测试方法?
在这种情况下,我总是强烈要求对其进行测试,好像受保护的方法将在公共方法中内联。
您想测试班级的外部行为。不是实施。受保护的方法是 test 不应该关心的实现细节。这意味着当您更改受保护的方法时,您必须更改测试。
从此开始:
class CTest extends PHPUnit_Framework_TestCase {
public function testM1NormalBehavior() {
}
/**
* @expectedException YourException
*/
public function testM1ThrowsExceptionWhenM2ConditionsAreMet() {
$c = new C('set_Up_In_A_Way_That_Makes_M2_Return_X');
$c->m1();
}
}
答案 1 :(得分:3)
您可以使用C
的部分模拟来强制m2()
返回"x"
。我假设extends PHPUnit_Framework_TestCase
是偶然的,C
实际上是被测试的类,而不是单元测试本身。
class CTest extends PHPUnit_Framework_TestCase {
/**
* @expectedException Exception
*/
function testM1ThrowsExceptionWhenM2ReturnsX() {
$c = $this->getMock('C', array('m2'));
$c->expects($this->once())->method('m2')->will($this->returnValue('x'));
$c->m1();
}
}