Laravel 5.6 对成员函数 beginTransaction() 的单元测试调用 null
Laravel 5.6 Unit Test Call to a member function beginTransaction() on null
我有一个 Laravel 项目 运行ning 版本 5.6。
连接的数据库是 mongodb 和 jenssegers/mongodb 包。
我写了一个单元测试来测试与用户相关的功能。
测试在配置的测试 mongodb 数据库中创建新用户。
我想在每次测试 运行 后刷新数据库,所以我使用 RefreshDatabase
特征。
使用 RefreshDatabase
特性时,我在 运行 测试时出现以下错误:
There was 1 error:
1) Tests\Unit\UserTest::it_gets_top_user
Error: Call to a member function beginTransaction() on null
当不使用 Trait 时,测试会在数据库中创建所有必要的内容,并在没有错误的情况下执行断言。
测试看起来像这样:
/** @test */
public function it_gets_top_user()
{
factory(\App\Users\User::class, 5)->create();
$userOne = factory(\App\Users\User::class)->create([
'growth' => 10
]);
$topUser = Users::getTopUser();
$collection = new Collection();
$collection->push($userOne);
$this->assertEquals($collection, $topUser);
}
我在 composer.json 中使用以下版本:
"laravel/framework": "5.6.*",
"jenssegers/mongodb": "3.4.*",
"phpunit/phpunit": "~7.0",
服务器上使用了以下版本:
- PHP 7.2
- MongoDB 3.4
- PHP MongoDB 扩展 1.4.2
我使用安装在供应商目录中的 phpunit 调用测试:
vendor/phpunit/phpunit/phpunit
问题似乎是,RefreshDatabase
特性对于 MongoDB 环境根本不起作用。
我通过在 Laravel 项目的 testing/
目录中创建自己的 RefreshDatabase
Trait 解决了上述问题。
特征看起来像这样:
<?php
namespace Tests;
trait RefreshDatabase
{
/**
* Define hooks to migrate the database before and after each test.
*
* @return void
*/
public function refreshDatabase()
{
$this->dropAllCollections();
}
/**
* Drop all collections of the testing database.
*
* @return void
*/
public function dropAllCollections()
{
$database = $this->app->make('db');
$this->beforeApplicationDestroyed(function () use ($database) {
// list all collections here
$database->dropCollection('users');
});
}
}
为了启用此 Trait,我覆盖了 TestCase
Class 中的 setUpTraits
函数。现在看起来像这样:
/**
* Boot the testing helper traits.
*
* @return array
*/
protected function setUpTraits()
{
$uses = array_flip(class_uses_recursive(static::class));
if (isset($uses[\Tests\RefreshDatabase::class])) {
$this->refreshDatabase();
}
if (isset($uses[DatabaseMigrations::class])) {
$this->runDatabaseMigrations();
}
if (isset($uses[DatabaseTransactions::class])) {
$this->beginDatabaseTransaction();
}
if (isset($uses[WithoutMiddleware::class])) {
$this->disableMiddlewareForAllTests();
}
if (isset($uses[WithoutEvents::class])) {
$this->disableEventsForAllTests();
}
if (isset($uses[WithFaker::class])) {
$this->setUpFaker();
}
return $uses;
}
最后在我所有的测试中 类 我可以像这样使用我新创建的特征:
<?php
namespace Tests\Unit;
use Illuminate\Database\Eloquent\Collection;
use Tests\RefreshDatabase;
use Tests\TestCase;
class UserTest extends TestCase
{
use RefreshDatabase;
// tests happen here
}
我有一个 Laravel 项目 运行ning 版本 5.6。 连接的数据库是 mongodb 和 jenssegers/mongodb 包。
我写了一个单元测试来测试与用户相关的功能。
测试在配置的测试 mongodb 数据库中创建新用户。
我想在每次测试 运行 后刷新数据库,所以我使用 RefreshDatabase
特征。
使用 RefreshDatabase
特性时,我在 运行 测试时出现以下错误:
There was 1 error:
1) Tests\Unit\UserTest::it_gets_top_user Error: Call to a member function beginTransaction() on null
当不使用 Trait 时,测试会在数据库中创建所有必要的内容,并在没有错误的情况下执行断言。
测试看起来像这样:
/** @test */
public function it_gets_top_user()
{
factory(\App\Users\User::class, 5)->create();
$userOne = factory(\App\Users\User::class)->create([
'growth' => 10
]);
$topUser = Users::getTopUser();
$collection = new Collection();
$collection->push($userOne);
$this->assertEquals($collection, $topUser);
}
我在 composer.json 中使用以下版本:
"laravel/framework": "5.6.*",
"jenssegers/mongodb": "3.4.*",
"phpunit/phpunit": "~7.0",
服务器上使用了以下版本:
- PHP 7.2
- MongoDB 3.4
- PHP MongoDB 扩展 1.4.2
我使用安装在供应商目录中的 phpunit 调用测试:
vendor/phpunit/phpunit/phpunit
问题似乎是,RefreshDatabase
特性对于 MongoDB 环境根本不起作用。
我通过在 Laravel 项目的 testing/
目录中创建自己的 RefreshDatabase
Trait 解决了上述问题。
特征看起来像这样:
<?php
namespace Tests;
trait RefreshDatabase
{
/**
* Define hooks to migrate the database before and after each test.
*
* @return void
*/
public function refreshDatabase()
{
$this->dropAllCollections();
}
/**
* Drop all collections of the testing database.
*
* @return void
*/
public function dropAllCollections()
{
$database = $this->app->make('db');
$this->beforeApplicationDestroyed(function () use ($database) {
// list all collections here
$database->dropCollection('users');
});
}
}
为了启用此 Trait,我覆盖了 TestCase
Class 中的 setUpTraits
函数。现在看起来像这样:
/**
* Boot the testing helper traits.
*
* @return array
*/
protected function setUpTraits()
{
$uses = array_flip(class_uses_recursive(static::class));
if (isset($uses[\Tests\RefreshDatabase::class])) {
$this->refreshDatabase();
}
if (isset($uses[DatabaseMigrations::class])) {
$this->runDatabaseMigrations();
}
if (isset($uses[DatabaseTransactions::class])) {
$this->beginDatabaseTransaction();
}
if (isset($uses[WithoutMiddleware::class])) {
$this->disableMiddlewareForAllTests();
}
if (isset($uses[WithoutEvents::class])) {
$this->disableEventsForAllTests();
}
if (isset($uses[WithFaker::class])) {
$this->setUpFaker();
}
return $uses;
}
最后在我所有的测试中 类 我可以像这样使用我新创建的特征:
<?php
namespace Tests\Unit;
use Illuminate\Database\Eloquent\Collection;
use Tests\RefreshDatabase;
use Tests\TestCase;
class UserTest extends TestCase
{
use RefreshDatabase;
// tests happen here
}