gpt4 book ai didi

PHPUnit在实例化后将类的实例变成模拟

转载 作者:IT王子 更新时间:2023-10-29 00:05:13 26 4
gpt4 key购买 nike

有没有办法用 PHPUnit 创建一个模拟类,然后我可以使用它的类名创建一个新实例?

我有一个定义了两个方法的接口(interface)。像这样的东西:

interface FooInterface {
function getA();
function getB();
}

然后我有另一个类接受类名,创建该类的一个实例,检查它是否是它所期望的实例 (FooInterface),然后调用该类的两个方法来获取一些信息。

class FooInfo {
protected $a;
protected $b;

public function __construct($fooClass) {
$foo = new $fooClass;

if (!($foo instanceof FooInterface)) {
throw new \Exception();
}

$this->a = $foo->getA();
$this->b = $foo->getB();
}
}

我知道如何很好地模拟一个对象。问题是,由于此类接受类名而不是对象(它是管理器的一部分,根据需要创建给定类的实例),我不能使用普通的模拟对象。

我尝试创建一个模拟对象然后使用该类名。它似乎可以很好地创建对象,甚至似乎具有我模拟的功能。但是,它似乎并不遵循我稍后设置的 will($this->returnValue('myValue')) 部分。

public function testConstruct()
{
$foo = $this->getMockForAbstractClass('Foo', array('getA', 'getB'));
$foo->expects($this->any())->method->('getA')->will($this->returnValue('a'));
$foo->expects($this->any())->method->('getB')->will($this->returnValue('b'));

$copyClass = get_class($foo);
$copy = new $copyClass();

// Passes
$this->assertTrue(method_exists($copy, 'getA');

// Fails, $copy->getA() returns null.
$this->assertEquals($copy->getA(), $foo->getA());
}

因此,它确实具有被模拟的函数,但它们都返回 null。

有什么想法吗?

最佳答案

在类的构造函数中使用 new 关键字是一个相当糟糕的习惯,正是由于您现在遇到的原因,即使您的用例很灵活。

您的测试将无法运行,因为您创建的模拟将永远不会被使用,因为您的类将始终创建注入(inject)类名的真实实例。

就是说,你想做的可以用padraic来完成优秀的模拟库 mockery !您需要的是“实例模拟”:

$mock = \Mockery::mock('overload:MyNamespace\MyClass');

您可以定义您对该模拟的期望,该模拟将在实例化后立即转移到真实对象。

将 mockery 与 phpUnit 集成很容易,并且在项目的自述文件中有很好的解释。

顺便说一句。每个单元测试最好只做出一个断言!

关于PHPUnit在实例化后将类的实例变成模拟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14615204/

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