Laravel 5 单元测试 - 在 null 上调用成员函数 connection()
Posted
技术标签:
【中文标题】Laravel 5 单元测试 - 在 null 上调用成员函数 connection()【英文标题】:Laravel 5 Unit Test - Call to a member function connection() on null 【发布时间】:2017-07-19 15:44:15 【问题描述】:我尝试为我的User
和Shop
模型之间的关系创建一个单元测试,但是当我运行vendor\\bin\\phpunit
时会抛出这个错误,因为我是新手,所以我对此一无所知在单元测试中。我试图在我的控制器上运行我的代码以查看关系是否真的有效,幸运的是它按预期工作,但在 phpunit 中运行时却没有。我做错了什么让这个 phpunit 不能与模型一起工作?
Fatal error:
Uncaught Error: Call to a member function connection() on null in E:\projects\try\vendor\laravel\framework\src\Illuminate\Database\Eloquent\Model.php:1013
Stack trace:
E:\projects\try\vendor\laravel\framework\src\Illuminate\Database\Eloquent\Model.php(979): Illuminate\Database\Eloquent\Model::resolveConnection(NULL)
这是我的 UserTest.php
<?php
namespace Tests\Unit;
use Tests\TestCase;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use App\User;
use App\Shop;
class UserTest extends TestCase
protected $user, $shop;
function __construct()
$this->setUp();
function setUp()
$user = new User([
'id' => 1,
'first_name' => 'John',
'last_name' => 'Doe',
'email' => 'JohnDoe@example.com',
'password' => 'secret',
'facebook_id' => null,
'type' => 'customer',
'confirmation_code' => null,
'newsletter_subscription' => 0,
'last_online' => null,
'telephone' => null,
'mobile' => null,
'social_security_id' => null,
'address_1' => null,
'address_2' => null,
'city' => null,
'zip_code' => null,
'signed_agreement' => 0,
'is_email_confirmed' => 0
]);
$user = User::find(1);
$shop = new Shop([
'id' => 1,
'user_id' => $user->id,
'name' => 'PureFoods Hotdog2',
'description' => 'Something that describes this shop',
'url' => null,
'currency' => 'USD'
]);
$user->shops()->save($shop);
$shop = new Shop([
'id' => 2,
'user_id' => $user->id,
'name' => 'PureFoods Hotdog',
'description' => 'Something that describes this shop',
'url' => null,
'currency' => 'USD'
]);
$user->shops()->save($shop);
$this->user = $user;
/** @test */
public function a_user_has_an_id()
$user = User::find(1);
$this->assertEquals(1, $user->id);
/** @test */
public function a_user_has_a_first_name()
$this->assertEquals("John", $this->user->first_name);
/** @test */
public function a_user_can_own_multiple_shops()
$shops = User::find(1)->shops()->get();
var_dump($this->shops);
$this->assertCount(2, $shops);
看来,这个错误是由这行代码引起的:
$user->shops()->save($shop);
- 此代码在我的示例路由或控制器中运行时实际上有效,但在 phpunit
中运行时抛出 errors
User.php
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
use Notifiable;
protected $guarded = [ 'id' ];
protected $table = "users";
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* returns the Shops that this user owned
*/
public function shops()
return $this->hasMany('App\Shop');
Shop.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Shop extends Model
protected $guarded = [ 'id' ];
protected $table = "shops";
/**
* returns the Owner of this Shop
*/
public function owner()
return $this->belongsTo('App\User');
任何帮助将不胜感激。谢谢!
【问题讨论】:
【参考方案1】:首先,setUp()
在每次测试之前被调用,所以你不应该在构造函数中调用它
其次,您应该调用 setUp()
中的 parent::setUp()
来初始化应用实例。
【讨论】:
【参考方案2】:您将 id '2' 分配给两个商店。
分配 is 不是必须的,因为我假设 shop table id 字段是一个自动增量字段。
还可以查看database factories in the Laravel docs,它会为您简化事情。
【讨论】:
【参考方案3】:示例:
<?php
class ExampleTest extends TestCase
private $user;
public function setUp()
parent::setUp();
$this->user = \App\User::first();
public function testExample()
$this->assertEquals('victor@castrocontreras.com', $this->user->email);
【讨论】:
【参考方案4】:问题的原因:你不能使用在类 UserTest 的构造函数中调用的代码中的 Laravel 模型功能 - 即使你把代码放在方法“setUp”中,你也没有必要调用它从构造函数。 SetUp 由 phpUnit 调用,无需在构造函数中进行。
当 UserTest 构造函数运行时,Laravel Bootstrap 代码还没有被调用。
当调用 UserTest->setUp() 方法时,Laravel Bootstrap 代码已经运行,所以你可以使用你的模型等。
class UserTest extends TestCase
protected $user, $shop;
function __construct()
$this->setUp(); // **THIS IS THE PROBLEM LINE**
function setUp()
$user = new User([....
【讨论】:
【参考方案5】:当您尝试从 dataprovider 函数读取数据库时,可能会发生这种情况。像我试过的,是的。工作方式:
protected static $tariffs_default;
protected function setUp(): void
parent::setUp ();
if (!static::$tariffs_default)
static::$tariffs_default = DB::...;
// in dataprovider we use string parm, named as our static vars
public static function provider_prov2()
return [
[".....", [ 'tariffs'=>'tariffs_default'] ],
];
// then, in test we can ask our data by code:
public function testSome(string $inn, string $ogrn, $resp_body)
if ( $ta_var = Arr::get( $resp_body, 'tariffs' ) )
Arr::set($resp_body, 'tariffs', static::$$ta_var );
$this->assert...
【讨论】:
谢谢。这就是发生在我身上的原因。在我发现这个之前,我看起来很困惑。【参考方案6】:还有一个原因
检查测试类是否在扩展 use Tests\TestCase; 而不是 use PHPUnit\Framework\TestCase;
Laravel 附带了后者,但 Tests\TestCase 类负责设置应用程序,否则模型在扩展 PHPunit\Framework\ 时将无法与数据库通信测试用例。
【讨论】:
(它说要避免这种类型的 cmets...)但是谢谢!!!!!!。我已经坚持了 2 天了!!!!!!! 但是我对此有点困惑,为什么默认样板使用 PHPUnit\Framework\TestCase 呢?为什么要使用 Tests\TestCase 的替代品? 对于基本测试,我认为您不会想要设置 Tests\TestCase 所做的应用程序。我认为这就是我不确定的原因。你可以问问 laravel 团队。【参考方案7】:解决方案
使用 PHPunit\Framework\TestCase
放这个
使用测试\TestCase
【讨论】:
似乎this的重复答案以上是关于Laravel 5 单元测试 - 在 null 上调用成员函数 connection()的主要内容,如果未能解决你的问题,请参考以下文章
Laravel 5.5 中 PHP 单元测试中的类验证器错误