gpt4 book ai didi

PHPunit 模拟仅观察

转载 作者:可可西里 更新时间:2023-11-01 00:15:18 24 4
gpt4 key购买 nike

我在理解模拟对象时遇到了一些问题。

我想要的是一个正常工作但确保使用正确参数调用方法的观察器。

据我目前的了解,这应该是我正在寻找的:观察者:

class Observer
{
public function returnFooIfBar($bar)
{
return ($bar == 'bar') ? 'foo' : ;
}
}

主题:

class Subject
{
$obs;
__construct(Observer $dependency)
{
$this->obs = $dependency;
}

public function tradeStrings($string)
{
$this->obs->returnFooIfBar($string);
}
}

测试:

class SubjectTest
{
public function testCallsObsMethod()
{
$obs = $this->getMock('Observer') ;
$obs->expect($this->once())
->method('returnFooIfBar')
->with($this->equlTo('bar')) ;

$subj = new Subject($obs);
$returnString= $subj->TradeStrings('bar') ;

$this->assertEqual('foo', $returnString) ;
}
}

据我了解,此测试:

  1. Observer::getFooIfBar 被调用一次。
  2. Observer::getFooIfBar 得到字符串 'bar'3.该方法按照类中定义的方式工作,并以字符串形式返回“foo”。

据我所知,除了不运行构造函数/自动加载之外,原始类的功能没有改变。

如果我在运行 getMock() 时模拟一个方法,模拟对象的方法将返回一些我指定的东西。

$obs = $this->getMock('Observer', array('returnFooIfBar'));
$obs->expects($this->once())
->method('returnFooIfBar')
->with('bar')
->will($this->returnValue('foo');

我理解的对吗?如果不能,请您为我澄清一下,因为我希望对此有所澄清。 :)

编辑:更改了帖子以更清楚地说明我所追求的内容以及我目前的理解方式。

最佳答案

如果您让 phpunit 创建一个模拟对象,它会在内部构建一个新的临时类,该临时类扩展原始类并使用模拟特定代码实现此类的所有方法。

这背后的想法是解耦测试用例中的对象。虽然您给出的示例是有效的,但您不会以这种方式使用它。但是您的示例测试无论如何都会失败,因为模拟函数 returnStringFooIfBar 不会返回任何内容。

它应该是这样工作的:

$obs = $this->getMock('observer') ;
$obs->expect($this->once())
->method('returnStringFooIfBar')
->with($this->equlTo('bar'))
->will($this->returnValue('foo'));

$returnString= $obs->returnStringFooIfBar ('bar') ;
$this->assertEqual('foo', $returnString) ;

但是真实世界的测试用例会涉及一些要测试的对象:

class TestObject {

private $observer;
public function __construct($observer) {
$this->observer = $observer;
}

public function doMagicAndNotify() {
// do heavy magic

//notify observer
$obsresult = $this->observer->returnStringFooIfBar('bar');

return 'didmagic';
}
}

class TestObjectTest extends PHPUnit_Framework_TestCase {

public function testObserverCalling() {
$obs = $this->getMock('observer') ;
$obs->expect($this->once())
->method('returnStringFooIfBar')
->with($this->equlTo('bar'));

$test = new TestObject($obs);
$returnString= $test->doMagicAndNotify() ;

$this->assertEqual('didmagic', $returnString) ;
}
}

编辑:

What I want is an observer that works normally but do make sure the methods are called with the right parameters.

As I understand no functionality of the original class is changed, other than the constructor / autoloading not being run.

其实恰恰相反。 Observer 的临时子类覆盖所有(或指定的)方法并更改原始功能(模拟方法的父类根本不执行)。它不会覆盖构造函数,它无论如何都会被调用。

不可能断言模拟方法的方法调用并同时调用其原始方法。

参见 Method Templatethe Generator供引用。

请记住:您不是在这里测试观察者的正确行为,您是在 mock 它的行为以测试对象。

sitenote:$this->returnCallback($someCallback) 是一个强大的函数,可能会对您有所帮助。我不喜欢这个主意,但你可以这样做:

public function testObserverCalling() {
$obs = new Observer();
$obsmock = $this->getMock('observer') ;
$obsmock->expect($this->once())
->method('returnStringFooIfBar')
->with($this->equlTo('bar'))
->will($this->returnCallback(array($obs, 'returnStringFooIfBar')));

$test = new TestObject($obsmock);
$returnString= $test->doMagicAndNotify() ;

$this->assertEqual('didmagic', $returnString) ;
}

关于PHPunit 模拟仅观察,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13180889/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com