在构造函数中调用的 phpunit 模拟方法

phpunit mock method called in constructor

我测试了一个配置 class,它正在解析一个配置文件并允许我获取应用程序的各种设置。

我的目标是模拟在构造函数中调用的 Config class 的 parse() 方法,并设置此方法在构造函数中返回的内容。

这样,它可以防止 file_get_contents() 被调用(在 parse() 方法中)并使我能够使用 config [=34] 进行配置 class =] 已经设置为包含属性数组。

但我还没有成功。

代码如下:

配置class:

<?php namespace Example;

use Symfony\Component\Yaml\Parser;

class Config
{

private $parser;
private $config;

public function __construct(Parser $parser, $filePath)
{
    $this->parser = $parser;
    $this->config = $this->parse($filePath);
}

public function parse($filePath)
{
    $fileAsString = file_get_contents($filePath);

    if (false === $fileAsString) {
        throw new \Exception('Cannot get config file.');
    }

    return $this->parser->parse($fileAsString);
}

public function get($path = null)
{
    if ($path) {
        $config = $this->config;

        $path = explode('/', $path);

        foreach ($path as $bit) {
            if (isset($config[$bit])) {
                $config = $config[$bit];
            }
        }

        return $config;

    }

    return false;
    }

}

测试:

<?php namespace Example;

class ConfigTest extends \PHPUnit_Framework_TestCase
{

    private function getConfigTestMock($configAsArray)
    {
        $parser = $this->getMockBuilder('\Symfony\Component\Yaml\Parser')
            ->getMock();

        $configMock = $this->getMockBuilder('Example\Config')
            ->setConstructorArgs([$parser, $configAsArray])
            ->setMethods(['parse', 'get'])
            ->getMock();

        $configMock->expects($this->once())
            ->method('parse')
            ->willReturn($configAsArray);

        return $configMock;
    }

    /**
     * @test
     */
    public function get_returns_false_if_no_path_given()
    {
        $configMock = $this->getConfigTestMock(['param1' => 'value1']);

        // Testing further...

    }
}

要测试 Config class,您只需模拟 Parser 并使用真实配置 class。例如:

<?php


namespace Acme\DemoBundle\Tests;


use Acme\DemoBundle\Example\Config;

class ConfigTest extends \PHPUnit_Framework_TestCase
{

    private function getConfigTestMock($configAsArray)
    {
        $parser = $this->getMockBuilder('\Symfony\Component\Yaml\Parser')
            ->getMock();


        $parser->expects($this->once())
            ->method('parse')
            ->willReturn($configAsArray);

        $configMock = new Config($parser,"fakePath");

        return $configMock;
    }

    /**
     * @test
     */
    public function get_returns_false_if_no_path_given()
    {
        $configMock = $this->getConfigTestMock(['param1' => 'value1']);
        $this->assertEquals("value1",$configMock->get("param1"));

        // Testing further...

    }
}

希望对您有所帮助

我建议你做一个功能测试来模拟与文件系统的交互,而不是对被测试的部分模拟 class。

我最近发现了 William Durand 关于 Symfony2 和 DDD 的vfsStream library used in a great article

所以你可以在你的 composer.json 中安装这个库(我用 1.4 版本测试了这个解决方案)并尝试这个示例测试 class:

<?php


namespace Acme\DemoBundle\Tests;


use Acme\DemoBundle\Example\Config;
use org\bovigo\vfs\vfsStream;
use Symfony\Component\Yaml\Parser;

class ConfigTest extends \PHPUnit_Framework_TestCase
{


    /**
     * @test
     */
    public function valid_content()
    {
        $content = "param1: value1";

        $root      = vfsStream::setup();

        $file = vfsStream::newFile('example.txt')
            ->withContent($content)
            ->at($root);

        $filepath = $file->url();
        $parser = new Parser();

        $config = new Config($parser, $filepath);
        $this->assertEquals("value1", $config->get("param1"));

    }

}

希望对您有所帮助