有没有办法模拟telnet类,控制登录功能的响应?
不容易。创建 telnet 类的模拟 很 很容易,但是 pon_validate_device() 函数会创建具体的 Telent 对象(newTelnet() ),没有简单的方法可以在调用其登录方法的地方注入要使用的模拟:
$testConnection = new Telnet(...);
$testConnection->login();
所以你应该认为这是不可能的,除非函数 pon_validate_device() 允许注入,例如使用(附加)函数参数:
function pon_validate_device(
DB $db,
Logger $logger,
$request, $mode = 'add',
Telnet $testConnection = null, # new parameter
) {
...
$testConnection ?= new Telnet(...);
$testConnection->login();
return true;
}
然后您可以注入(在您的测试中)模拟。
通过将其设为非可选参数,可以使这种依赖关系更加明显。
由于该函数已经有四个(三加一可选)参数,看起来已经有点拥挤了。
参数注入的替代方法是构造函数注入。这可能需要您将函数转换为对象并实例化它:
class PonDevice {
public function __construct(
private DB $db,
private Logger $logger,
private Telnet $telnet,
) {}
...
public function validate($request, $mode = 'add') {
...
$this->telnet->login(???);
return true;
}
}
正如您在这个快速示例中已经看到的那样,它可能会冒泡初始化要求,例如参数化了什么
$testConnection = new Telnet(...);
现在已经被注入了,所以 Telnet 类可能需要额外的改变(如果 Telnet 构造函数做了实际工作,这可能很好,因为它使这些类很难在测试中使用 - 从构造函数注入带参数的方法,用问号快速勾勒:
$this->telnet->login(???);
已经说了很多,主要的收获应该是,如果测试表明某些代码很难测试,它可能会揭示以前更多隐藏的依赖关系。考虑一下正在发生的事情,并考虑代码是否可以从设计更改中受益(只有当它使被测系统更容易为您使用/开发时才有好处,例如测试工作轻而易举,您可以然后更快更安全地更改更多代码)。
现在是脏的部分(湿的时候很滑,而且总是湿的情况):
鉴于被测代码尚未执行,更重要的是,从未实例化过 Telnet 类并且正在使用自动加载,您可以“模拟” Telnet 类定义,将其替换为您自己的(具有相同的类名)。
当代码随后执行时,它将根据该类定义实例化 Telnet 对象,因为不再有任何东西可以自动加载。
但是,这需要您完全复制 Telnet 类,然后为该测试添加双倍类特定测试点以注入仅测试行为和属性。
正如您可以想象的那样,这很麻烦、不稳定、维护起来很混乱,而且无法进一步改进被测代码。
但是我认为你要求它,至少应该在答案中提到它。