我有一个有趣的问题并且已经在互联网上搜索过,但还没有找到答案。
我为一家不允许工人使用OOP的公司工作,这有点荒谬,但工作经验很有价值。
考虑以下功能:
function get_setting_values_from_file( $parameter )
{
exec("/usr/var/binary --options $parameter", $output, $return);
$settings = file( $output[0] );
foreach( $settings as $setting ) {
if( strstr( $setting, "color") ) {
$setting = explode( ":", $setting );
return $setting[1];
}
}
return false;
}
我需要对类似功能进行单元测试。我目前正在使用phpUnit进行测试,使用vfsStream库来模拟文件系统,但是当我开发时无法访问实际系统时,如何模拟对exec("/usr/var/binary --options $parameter", $output, $return)
的调用?处理这样的测试用例的推荐方法是什么?
感谢所有反馈。
答案 0 :(得分:4)
您可以使用函数模拟库来模拟exec()
。我为你做了一个(php-mock
),要求你使用命名空间
namespace foo;
use phpmock\phpunit\PHPMock;
class ExecTest extends \PHPUnit_Framework_TestCase
{
use PHPMock;
public function testExec()
{
$mock = $this->getFunctionMock(__NAMESPACE__, "exec");
$mock->expects($this->once())->willReturnCallback(
function ($command, &$output, &$return_var) {
$this->assertEquals("foo", $command);
$output = "failure";
$return_var = 1;
}
);
exec("foo", $output, $return_var);
$this->assertEquals("failure", $output);
$this->assertEquals(1, $return_var);
}
}
答案 1 :(得分:1)
只需模拟此函数即可返回您尝试进入$ settings的文本。您无需调用可执行文件,只需创建文件或返回。
例如,假设函数get_setting_values_from_file()将设置作为数组返回,您可以简单地模拟测试中的函数以将设置作为数组返回。创建一个测试存根来模拟包含get_setting_values_from_file()方法的对象,并让该模拟只返回测试所假设的相同的FALSE,1或2。
$stub = $this->getMock('GetSettingsClass');
$stub->expects($this->any())
->method('get_settings_from_file')
->will($this->returnValue(0));
这是来自PHPUnit手册 - > http://phpunit.de/manual/3.8/en/test-doubles.html#test-doubles.stubs
或者,您甚至可以绕过调用,只需通过创建数组并将其传递给这些函数来测试对返回有效的函数/代码。 主代码中的假设示例:
...
$settings = get_setting_values_from_file( 'UserType' );
$UserType = get_user_type($settings);
return $UserType;
function get_user_type($settings)
{
if($settings !== FALSE) // Returned from your function if parameter is not found
{
switch($settings)
{
case 1:
return 'User'; // Best to use Constants, but for example here only
break;
case 2:
return 'Admin';
break;
...
}
}
else
{
return FALSE;
}
}
现在,在您的测试中,您可以简单地
$this->assertFalse(get_user_type(FALSE, 'Ensure not found data is handled properly as FALSE is returned');
$this->assertEqual('User', get_user_type(1), 'Test UserType=1');
$this->assertEqual('Admin', get_user_type(1), 'Test UserType=2');
...
这些工作因为代码不调用必须模拟从OS读取的函数,但通过调用处理设置返回值的函数来处理所有预期的返回。在这里,您只需假设从函数'get_setting_values_from_file()'返回,而不需要文件或任何模拟。
这不会测试从文件读取,我会在另一个测试中通过使用setUp和tearDown来实际创建一个包含你想要的值的文件(fopen / fwrite),然后调用你的函数并确保它返回期待什么。
我希望这有助于解释我的想法。