Laravel单元测试:运行多个测试方法时出现重定义错误



在阅读了这里需要活动数据库连接的示例后,我正在尝试运行一组单元测试。它似乎适用于一个单元测试,但由于重新定义 Laravel Command 类中包含的常量,它将在多个测试中失败。以下是我在运行 PHP Unit 后收到的错误:

PHPUnit 3.7.31 by Sebastian Bergmann.
FEE
Time: 203 ms, Memory: 5.00Mb
There were 2 errors:
1) MessageControllerTest::testSixMonths
ErrorException: Constant SHARE_SEND_EXPIRATION already defined
src/app/commands/DeleteExpiredSends.php:31
src/app/start/artisan.php:14
src/vendor/laravel/framework/src/Illuminate/Console/start.php:57
src/vendor/laravel/framework/src/Illuminate/Console/Application.php:30
src/vendor/laravel/framework/src/Illuminate/Foundation/Artisan.php:70
src/vendor/laravel/framework/src/Illuminate/Foundation/Artisan.php:45
src/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php:206
src/app/tests/MessageControllerTest.php:46
src/app/tests/MessageControllerTest.php:46
src/app/tests/MessageControllerTest.php:21
2) MessageControllerTest::testOneYear
ErrorException: Constant SHARE_SEND_EXPIRATION already defined
src/app/commands/DeleteExpiredSends.php:31
src/app/start/artisan.php:14
src/vendor/laravel/framework/src/Illuminate/Console/start.php:57
src/vendor/laravel/framework/src/Illuminate/Console/Application.php:30
src/vendor/laravel/framework/src/Illuminate/Foundation/Artisan.php:70
src/vendor/laravel/framework/src/Illuminate/Foundation/Artisan.php:45
src/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php:206
src/app/tests/MessageControllerTest.php:46
src/app/tests/MessageControllerTest.php:46
src/app/tests/MessageControllerTest.php:21
FAILURES!
Tests: 3, Assertions: 1, Errors: 2.

这是我的单元测试:

<?php
class MessageControllerTest extends TestCase
{
    /**
     * setUp() : set up the unit tests by initializing the database
     */
    public function setUp()
    {
        // call the parent's setup method
        parent::setUp();
        // init the DB
        $this->migrateDatabase();
    }
    /**
     * createApplication() : bootstrap the app in order to execute
     * tests
     *
     * @return SymfonyComponentHttpKernelHttpKernelInterface  
     */
    public function createApplication()
    {
        // set the unitTesting flag to true
        $unitTesting = true;
        // set the environment variable to 'testing'
        $testEnvironment = 'testing';
        return require __DIR__.'/../../bootstrap/start.php';
    }
    /**
     * migrateDatabase() : load the sqlite database into memory
     */
    private function migrateDatabase()
    {
        Artisan::call('migrate');
    }
    /**
     * testHundredFilesMessage() : tests to see if custom message will
     * return after 100 messages have been sent by the same user
     */
    public function testHundredFilesMessage()
    {
        // TODO
        $this->assertTrue(false);
    }
    /**
     * testSixMonthMessage() : test the six months message
     */
    public function testSixMonthMessage()
    {
        // TODO
        $this->assertTrue(false);
    }
    /**
     * testOneYearMessage() : test the one-year message
     */
    public function testOneYearMessage()
    {
        // TODO
        $this->assertTrue(false);
    }
}

第一个测试似乎通过了,但所有后续测试都会抛出错误。我猜 createApplication() 方法以某种方式被调用了几次,这可能解释了为什么CommandDeleteExpiredSends被重新定义;该类在其构造函数中显示define语句:

/**
 * Create a new command instance.
 *
 * @return void
 */
public function __construct()
{
    parent::__construct();
    define("SHARE_SEND_EXPIRATION", 14);
}

如果有人能告诉我如何避免重新定义这个单元测试,以避免修改Command类的内部结构,那将是最有帮助的。这似乎只是涉及此单元测试的问题。

对于每个测试方法,为 phpunit 添加两个注释,如下所示:

/* @runInSeparateProcess
 * @preserveGlobalState disabled
 */
public function testPageShow()
{
  • 运行在分离进程中:在单独的进程中运行每个测试
  • 保留全局状态已禁用:禁用先前测试的全局状态

我认为当您仍然不确定将您拥有的这些全局常量放在哪里时,对于临时解决方案,请使用defined

defined('SAMPLE_GLOBAL_CONSTANT')
  or define('SAMPLE_GLOBAL_CONSTANT', 'sample value of the constant')

顺便说一下,如果您也运行全局函数的重定义异常,您也可以使用function_exists方法。

但请务必使用 Class 来保存该全局函数,以便可以轻松测试应用程序。就像把它放在像Helper或更具体的东西上,比如StringHelper.

使用

SenseException 的解决方案删除所有define语句(事实证明,整个应用程序中只使用了两个语句),而是使用类常量确实解决了这个问题。

最新更新