【问题标题】:Setup and use parameters in PHPUnit data providers在 PHPUnit 数据提供者中设置和使用参数
【发布时间】:2018-01-06 17:19:11
【问题描述】:

我正在尝试为使用全局参数(来自 YML 文件)的服务编写测试。

我在 setUp() 方法中检索此参数,但是当我尝试在 @dataProvider 中使用它们时,它会引发错误。

class InterpreterServiceTest extends KernelTestCase
{
    private $container;
    private $service;
    private $citiesMap;

    public function setUp()
    {
        self::bootKernel();
        $this->container = self::$kernel->getContainer();
        $this->service = $this->container->get('geolocation.interpreter');
        $this->citiesMap = $this->container->getParameter("citiesmap");
        self::tearDown();
    }

    /**
     * @dataProvider locationsProvider
     */
    public function testCompanyCityFromCity($location, $expected)
    {
        $city = $this->service->getCompanyCityFromCity($location);
        $this->assertEquals($expected, $city);
    }

    public function locationsProvider()
    {
        $return = array();
        foreach ($this->citiesMap as $area) {
            $return[] = [
                $area['external_service_area'],
                $area['company_area']
            ];
        }
        return $return;
    }
}

为 foreach() 提供的参数无效

如果我手动编写 locationsProvider() 的返回值,它会起作用

return [
    ["Barcelona", "Barcelona"],
    ["Madrid", "Madrid"],
    ["Cartagena", "Murcia"]
];

我还检查了setUp() 中的 foreach,它返回了正确的预期数组。


@dataProvider 似乎是在 setUp() 方法之前执行的。

有没有其他方法可以做到这一点?

【问题讨论】:

    标签: php symfony phpunit


    【解决方案1】:

    担心您必须在dataProvider 方法中获取所有数据(包括服务对象)

    TL&DR应该这样做:

    class InterpreterServiceTest extends KernelTestCase
    {
        /**
         * @dataProvider locationsProvider
         */
        public function testCompanyCityFromCity($service, $location, $expected)
        {
            $city = $service->getCompanyCityFromCity($location);
    
            $this->assertEquals($expected, $city);
        }
    
        public function locationsProvider()
        {
            self::bootKernel();
    
            $container = self::$kernel->getContainer();
            $service = $this->container->get('geolocation.interpreter');
            $citiesMap = $this->container->getParameter("citiesmap");
            // self::tearDown(); - depends on what is in the tearDown
    
            $return = array();
            foreach ($citiesMap as $area) {
                $return[] = [
                    $service,
                    $area['external_service_area'],
                    $area['company_area']
                ];
            }
    
            return $return;
        }
    }
    

    原因:

    setUpsetUpBeforeClass 方法都在 PHPUnit_Framework_TestSuite 类的 run 方法中运行。 但是,dataProvider 中的数据是作为 createTest 函数的一部分较早计算的。

    【讨论】:

    • 我定义了一个_configured 标志,我将从每个dataProvider 调用setUp,所以它只会在第一次调用时运行。现在我可以添加或删除任何 dataProvider,即使我不从任何 dataProvider 调用原始 setUp 也可以正常工作。
    • 这也是为什么数据提供者必须是公开的或者可以来自不同类别的原因。
    • 我必须将 self::ensureKernelShutdown() 添加到提供程序的末尾才能使此解决方案起作用
    猜你喜欢
    • 1970-01-01
    • 2011-10-21
    • 2018-05-17
    • 2017-10-31
    • 2013-02-14
    • 2018-02-02
    • 1970-01-01
    • 2012-05-24
    • 1970-01-01
    相关资源
    最近更新 更多