【问题标题】:How can I reference external data providers in phpunit?如何在 phpunit 中引用外部数据提供者?
【发布时间】:2018-02-02 14:47:49
【问题描述】:

我正在尝试使用 PHPUnit 中的通用数据提供程序运行一些测试。

看下面的测试:

    namespace AppBundle\Tests\Controller;

    use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
    use AppBundle\Tests\DataProvider\XmlDataProvider;

    class DefaultControllerTest extends WebTestCase
    {
        /**
         * @dataProvider XmlDataProvider::xmlProvider
         * @covers ReceiveController::receiveAction()
         * @param string
         */
        public function testReceive($xml)
        {
            $client = static::createClient([], ['HTTP_HOST' => 'mt.host']);
            $client->request(
                'POST',
                '/receive',
                [],
                [],
                [],
                $xml
            );

            $response = $client->getResponse();
            $this->assertEquals(200, $response->getStatusCode());
        }
    }

现在我想要一个外部数据提供者类:

namespace AppBundle\Tests\DataProvider;

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

class XmlDataProvider extends WebTestCase
{
    /**
     * @dataProvider
     */
    public static function xmlProvider()
    {
        return array([
            'xml1' => '<?xml version="1.0" encoding="UTF-8"?><myTestableXml></myTestableXml>'
        ]);
    }
}

但是当我运行 phpunit 时,我得到:

1) 警告 指定的数据提供者 AppBundle\Tests\Controller\DefaultControllerTest::testReceive 是 无效的。 XmlDataProvider 类不存在

2) 警告 类中未找到测试 “AppBundle\Tests\DataProvider\XmlDataProvider”。

我该怎么做?

更新

composer.json 自动加载 sn -p 供参考:

"autoload": {
    "psr-4": {
        "AppBundle\\": "src/AppBundle",
        "Tests\\": "tests"
    },
    "classmap": [
        "app/AppKernel.php",
        "app/AppCache.php"
    ]
},
"autoload-dev": {
    "psr-4": {
        "Tests\\": "tests/"
    },
    "files": [
        "vendor/symfony/symfony/src/Symfony/Component/VarDumper/Resources/functions/dump.php"
    ]
},

【问题讨论】:

    标签: php symfony phpunit composer-php tdd


    【解决方案1】:

    您需要使用完全限定的类名来引用数据提供者:

    namespace AppBundle\Tests\Controller;
    
    use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
    
    class DefaultControllerTest extends WebTestCase
    {
        /**
         * @dataProvider \AppBundle\Tests\DataProvider\XmlDataProvider::xmlProvider
         * @covers ReceiveController::receiveAction()
         * @param string $xml
         */
        public function testReceive($xml)
        {
            // ...
        }
    }
    

    自动加载

    另外,请确保调整 composer.json 中的自动加载配置,以便可以自动加载数据提供程序(可能需要根据“AppBundle\Test”命名空间映射到的目录进行调整):

    {
        "autoload-dev": {
            "psr-4": {
                "AppBundle\\Tests\\": "tests/"
            }
        }
    }
    

    或者,既然您建议您的自动加载配置如下所示:

    {
        "autoload-dev": {
            "psr-4": {
                "Tests\\": "tests/"
            }
        }
    }
    

    您需要将您的命名空间从AppBundle\Tests 调整为Tests\AppBundle

    注意 与您的问题无关,但就我个人而言,我认为数据提供者不需要扩展 WebTestCase

    例如,请参阅:

    【讨论】:

    • 谢谢,但它仍然给我警告... :/ 1) 警告为 AppBundle\Tests\Controller\DefaultControllerTest::testReceive 指定的数据提供程序无效。类 \AppBundle\Tests\DataProvider\XmlDataProvider 不存在`
    • 你真的在使用\AppBundle\Tests\DataProvider\XmlDataProvider::xmlProvider()吗?
    • 是的,它提供了用于各种测试的 xml……嗯……这就是计划。还是你的意思是“使用”?
    • 如果断言assertTrue(class_exists(\AppBundle\Tests\DataProvider\XmlProvider::class) 通过,那么你应该很高兴。否则,a) 测试命名空间中的类的自动加载配置丢失或 b) 数据提供者的类名与其在项目目录结构中的位置不匹配。
    • 调整了我的答案以反映可能需要调整您的composer.json。顺便说一句,即使一开始可能不需要为开发资源自动加载,但最好从一开始就提供适当的autoload-dev 配置来记录它。这还有一个优点,即如果您开始提取抽象测试用例,或者 - 如您的示例 - 外部数据提供者,它可以立即工作。
    【解决方案2】:

    PHPUnit 提供程序自动加载器

    在 PHPUnit 中自动加载 CSV、JSON、PHP、XML 和 YAML 数据提供程序的魔术助手。

    安装

    composer require redaxmedia/phpunit-provider-autoloader
    

    用法

    为您的测试套件创建 TestCaseAbstract:

    <?php
    namespace ExampleProject\Tests;
    
    use PHPUnitProviderAutoloader;
    
    /**
     * TestCaseAbstract
     *
     * @since 2.0.0
     *
     * @package ExampleProject
     * @category Tests
     */
    
    abstract class TestCaseAbstract extends PHPUnitProviderAutoloader\TestCaseAbstract
    {
        /**
         * directory of the provider
         *
         * @var string
         */
    
        protected $_providerDirectory = 'tests' . DIRECTORY_SEPARATOR . 'provider';
    
        /**
         * namespace of the testing suite
         *
         * @var string
         */
    
        protected $_testNamespace = __NAMESPACE__;
    }
    

    从 TestCaseAbstract 扩展以自动加载 ExampleTest{_testMethod}.{csv|json|php|xml|yml} 文件:

    <?php
    namespace ExampleProject\Tests;
    
    /**
     * ExampleTest
     *
     * @since 2.0.0
     *
     * @package ExampleProject
     * @category Tests
     */
    
    class ExampleTest extends TestCaseAbstract
    {
        /**
         * testMethod
         *
         * @since 2.0.0
         *
         * @param string $expect
         *
         * @dataProvider providerAutoloader
         */
    
        public function testMethod(string $expect = null)
        {
            $this->assertEquals($expect, 'test');
        }
    }
    

    了解详情

    相关仓库:https://github.com/redaxmedia/phpunit-provider-autoloader

    示例集成:PHP test 自动加载 PHP class providerPHP method provider

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-21
      • 2014-11-19
      • 2018-01-06
      • 1970-01-01
      • 2018-05-17
      • 2018-07-01
      • 1970-01-01
      • 2013-02-14
      相关资源
      最近更新 更多