Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/291.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHPUnit:如何保存传递给存根方法的参数_Php_Mocking_Phpunit - Fatal编程技术网

PHPUnit:如何保存传递给存根方法的参数

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_框

类SomeClass中的方法setValue()接受参数,但无法为make断言获取此参数

我是否可以为方法setValue()创建存根,以便保存传递给此方法的参数


上课{
公共函数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
        );
    }
}
有关如何测试私家车的更多信息,请参见


您可以使用returnCallback执行任意代码,就像测试用例的测试助手方法一样。例如,如果setValueTester是testcase中的一个方法,则此期望将模拟上对setValue的调用重定向到它。参数可用于func_get_参数

$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  '));
  }
}