在阅读了这里需要活动数据库连接的示例后,我正在尝试运行一组单元测试。它似乎适用于一个单元测试,但由于重新定义 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() 方法以某种方式被调用了几次,这可能解释了为什么Command
类DeleteExpiredSends
被重新定义;该类在其构造函数中显示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
语句(事实证明,整个应用程序中只使用了两个语句),而是使用类常量确实解决了这个问题。