【问题标题】:PHPUnit setUp to run for an individual test with dataProviderPHPUnit setUp 使用 dataProvider 运行单个测试
【发布时间】:2026-01-07 16:50:01
【问题描述】:

我有一个 PHPUnit 测试 testFoo() 和一个 dataProvider fooProvider()。在testFoo() 的开头,我正在使用 Runkit 重新定义一个方法,以便在该方法返回我重新定义的返回值时测试预期结果。但是,重新定义该方法有点费时,所以我希望它在本次测试中只发生一次。

PHPUnit 框架是否提供功能来指定我希望在 testFoo() 运行之前只运行一次的代码,而不是为 fooProvider() 返回的每个元素或套件中的每个测试运行一次(如 setUp() )?

【问题讨论】:

  • @beforeClass 怎么样?
  • @xmike 我需要多次重新定义所述方法以针对不同的测试返回不同的东西,所以它确实需要针对单个测试
  • 我会留在你的@before,但我自己的提供者在测试中做类似$dataSets = $this->getDataSets() (应该返回你的数据数组),然后用里面的断言循环遍历它环形。这样测试将只由 PHPUnit 框架启动一次,因此 setUp() 也将只运行一次(从它的角度来看,测试将只运行一次)。
  • 我想我希望有一个@beforeTest 注释来指定一个在测试前运行一次的函数,这样我就不需要用循环和参考设置来混淆我的测试方法。但是从我可以从不存在的 PHPUnit 文档中看到?
  • 其实你是对的,@before 在每次测试前只运行一次。问题是,如果您使用@dataProvider,则为每个数据集重新启动测试,从而使@before 也被执行——这就是 PHPUnit 框架处理数据提供的方式(发生这种情况是因为必须在每个新的数据集并接收该新集作为参数)。所以避免重新启动的方法是不使用自动化的dataProviding。

标签: php unit-testing phpunit runkit


【解决方案1】:

使用静态私有属性来标记该方法已被重新定义。您需要它是静态的,因为测试类是为 dataProvider 提供的每个案例实例化的。

class FooTest extends PHPUnit_Framework_TestCase
{
    private static $redefined = false;

    /**
     * @dataProvider fooProvider
     */
    public function testFoo()
    {
        if (! self::$redefined) {

            // redefinition code goes here

            self::$redefined = true;
        }
    }
}

【讨论】:

  • 我希望在 PHPUnit 框架内找到一个解决方案(我将编辑我的问题以澄清这一点)。我在不同的测试中重新定义了相同的方法,最好不必手动跟踪每个方法以及是否已重新定义以及是否重新定义为每个测试的适当替代方法。
  • 在这种情况下,您可以拥有一个处理方法重新定义并在所有测试中使用的类。该类应该知道哪些方法已经被重新定义,并且在方法已经被重新定义的情况下什么也不做。
  • 这会起作用,但会是一种非常迂回的方式来防止方法被多次重新定义(与问题 cmets 中的 xmike 解决方法相比,或者与类似于 setup() 的某些函数相比) PHPUnit 框架)