有没有一种方法可以忽略PHPUnit 6模拟类的魔力?
假设我有一个类有没有一种方法可以忽略PHPUnit 6模拟类的魔力?,php,unit-testing,phpunit,Php,Unit Testing,Phpunit,假设我有一个类Foo,它有一个神奇的\u set()方法,可以防止在实例上设置任何不存在的属性: class Foo { public function __set($name, $value) { } } 如果我模拟它并尝试设置它没有的属性,如果它不工作,原因很明显: $foo_mock = $this->createMock(Foo::class); $foo_mock->bar = 'baz'; var_dump($foo_mock->bar); // NUL
Foo
,它有一个神奇的\u set()
方法,可以防止在实例上设置任何不存在的属性:
class Foo {
public function __set($name, $value) {
}
}
如果我模拟它并尝试设置它没有的属性,如果它不工作,原因很明显:
$foo_mock = $this->createMock(Foo::class);
$foo_mock->bar = 'baz';
var_dump($foo_mock->bar); // NULL
有没有一种方法可以忽略或重写magic\uu set()
方法,这样我就可以设置类中未定义的属性
我知道这是一个非常奇怪的用例,但我有一段特别不稳定的代码,我已经没有想法了。替换为Test Double
如果您只是想要一个可以设置任意属性的双重测试,那么您可以使用stdClass
。这取决于您希望使用Foo
的类型提示
$mock = new \stdClass;
$mock->foo = "bar";
var_dump($mock);
在线回复中的示例:
要测试的子类
如果类型提示为Foo
,则可以通过子类化Foo
并重写恶意魔法方法来创建模拟
class Foo {
public function __set($name, $value) {
var_dump(sprintf("__set %s %s", $name, $value));
die();
}
}
class MockFoo extends Foo {
public $set = array();
public function __set($name, $value) {
$this->set[$name] = $value;
}
}
function methodUnderTest(Foo $foo) {
$foo->something = "mhm";
}
methodUnderTest(new MockFoo());
repl中的示例:如果您强制模拟对象的行为与原始类的设计不同,那么我们可以说您实际上是在测试原始类吗 您可以执行类似于扩展
Foo
类的操作,并重写\u set()
方法,如下所示:
class Bar extends Foo {
public function __set($name, $value) {
$this->$name = $value
}
}
在测试中使用这个类而不是
Foo
,但是你不能声称你在测试Foo
,因为你在测试Bar
,不管它们在一种方法中是否不同,它们都不是 相同。您的意思是需要在$foo_mock上设置一个不存在的属性?不允许设置一个不存在的属性是类foo
的一种设计行为,我认为强制模拟对象以不同的方式操作会使您的测试无效,应该避免。@Nima您是对的,感谢您指出这一点。我将寻找一种不同的方法。在我的例子中,所有的参数都是类型提示的,因此stdClass
不起作用。也许如果您向我们展示更多关于您想要编写的实际测试或正在测试的方法的信息,我们可以为您指出正确的方向。