PHPUnit:如何保存传递给存根方法的参数
类SomeClass中的方法setValue()接受参数,但无法为make断言获取此参数 我是否可以为方法setValue()创建存根,以便保存传递给此方法的参数PHPUnit:如何保存传递给存根方法的参数,php,mocking,phpunit,Php,Mocking,Phpunit,类SomeClass中的方法setValue()接受参数,但无法为make断言获取此参数 我是否可以为方法setValue()创建存根,以便保存传递给此方法的参数 上课{ 公共函数setValue($name,$value) { //做点什么 } 公共函数doSomething(数组$value) { foreach($name=>$value形式的值){ $this->setValue($name,trim($value)); } } } 类TestSomeClass扩展了PHPUnit_框
上课{
公共函数setValue($name,$value)
{
//做点什么
}
公共函数doSomething(数组$value)
{
foreach($name=>$value形式的值){
$this->setValue($name,trim($value));
}
}
}
类TestSomeClass扩展了PHPUnit_框架_测试用例{
公共函数testDoSomething()
{
$mock=$this->getMock('SomeClass',array('setValue');
$mock->doSomething(数组('v1'=>'string');
//这里需要这样的断言
$this->assertEquals('string',$argumentPassedToSetValue);
}
}
否。不适用于实际测试对象
如果您的setValue
方法设置了非公共属性,您可以使用assertAttributeEquals
:
class SomeClass
{
protected $foo;
public function setFoo($val)
{
$this->foo = trim($val);
}
}
class SomeClassTest extends PHPUnit_Framework_TestCase
{
public function testSetFooTrimsArgument()
{
$testSubject = new SomeClass;
$testSubject->setFoo(' bar ');
$this->assertAttributeEquals(
'bar', /* expected value */
'foo', /* attribute name */
$testSubject
);
}
}
有关如何测试私家车的更多信息,请参见
$mock->expects($this->any())->method("setValue")->will($this->returnCallback(array($this,"setValueTester"));
关于如何测试设置是否有效,请参见@Gordons答案 我想说的是,你不需要测试它。 您的单元测试应该确保类的publicAPI按预期工作。您不关心(为了测试)您的值是如何在内部存储的,因此不需要对其进行断言。这样做也会让你的测试只测试你的班级做什么,而不是班级如何做 关键是,在更改类时,您不应该在不影响类功能的情况下更改测试 为了便于讨论,让我们假设SomeClass最终会输出HTML
class SomeClass {
public function setValue($name, $value)
{
// do some stuff
}
public function doSomething(array $values)
{
foreach ($values as $name=>$value) {
$this->setValue($name, trim($value));
}
}
public function createHTML()
{
$return = "";
foreach($this->values as $key => $value) {
$return .= "<div is='$key'>$value</div>";
}
return $return;
}
}
class-SomeClass{
公共函数setValue($name,$value)
{
//做点什么
}
公共函数doSomething(数组$value)
{
foreach($name=>$value形式的值){
$this->setValue($name,trim($value));
}
}
公共函数createHTML()
{
$return=“”;
foreach($this->value为$key=>$value){
$return.=“$value”;
}
return$return;
}
}
如果这就是您的类所做的一切,那么该类的绝对充分测试可能如下所示:
class SomeClassTest扩展了PHPUnit\u框架\u测试用例{
公共函数testHtmlGenerationWithTwoValuesSet(){
$o=新的SomeClass();
$o->setValue(“foo”,“bar”);
$o->setValue(“x”、“y”);
$result=$o->createHTML();
$this->assertSame(
2.
substr_计数(“,$result),
“div的数量应与设置的值的数量相同”
);
$this->assertTrue(
strpos(“bar”)!==false
“字符串应包含一个用div括起来的集合值”
);
}
}
再次强调:它是关于测试类的行为,而不是单独测试每个方法。如果您这样做,您的测试套件将更有价值
虽然html示例可能不是正确的,但它展示了如何非常好地测试行为(我希望)在这个简单的例子中,您可以指定希望传递给
setValue()
的参数
不过,我同意edorian的观点,您最好通过公共API测试类中的内容。直接测试内部实现意味着每次更改或重构时都要更新更多的测试
class SomeClass {
public function setValue($name, $value)
{
// do some stuff
}
public function doSomething(array $values)
{
foreach ($values as $name=>$value) {
$this->setValue($name, trim($value));
}
}
public function createHTML()
{
$return = "";
foreach($this->values as $key => $value) {
$return .= "<div is='$key'>$value</div>";
}
return $return;
}
}
class SomeClassTest extends PHPUnit_Framework_TestCase {
public function testHtmlGenerationWithTwoValuesSet() {
$o = new SomeClass();
$o->setValue("foo", "bar");
$o->setValue("x", "y");
$result = $o->createHTML();
$this->assertSame(
2,
substr_count("<div>", $result),
"There should be as many divs as there are values set"
);
$this->assertTrue(
strpos("<div>bar</div>") !== false
"String should contain a set value enclosed in divs"
);
}
}
class TestSomeClass extends PHPUnit_Framework_TestCase
{
public function testDoSomething()
{
$mock = $this->getMock('SomeClass', array('setValue'));
$mock->expects($this->once())->method('setValue')->with('v1', 'string');
$mock->doSomething(array('v1'=>' string '));
}
}