簡體   English   中英

Laravel 5 單元測試 - 在 null 上調用成員函數 connection()

[英]Laravel 5 Unit Test - Call to a member function connection() on null

我嘗試為我的UserShop模型之間的關系創建一個單元測試,但是當我運行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

用戶.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');
    }
}

商店.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');
    }
}

任何幫助將不勝感激。 謝謝!

還有一個原因

檢查測試類是否正在擴展使用 Tests\TestCase; 而不是使用 PHPUnit\Framework\TestCase;

Laravel 附帶了后者,但Tests\TestCase類負責設置應用程序,否則如果模型擴展PHPunit\Framework\TestCase ,它們將無法與數據庫通信。

首先, setUp()在每次測試之前都會被調用,所以你不應該在構造函數中調用它

其次,您應該在 setUp() 中調用parent::setUp() setUp()來初始化應用程序實例。

例子:

<?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);
   }
}

一個解法

使用 PHPunit\Framework\TestCase

把這個

使用測試\TestCase

您正在為兩家商店分配 id '2'。

分配 is 不應該是必需的,因為我假設 shop table id 字段是一個自動增量字段。

還可以查看Laravel 文檔中的數據庫工廠,它會為您簡化事情。

當您嘗試從 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...
}

問題的原因:您不能從在 Class 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([....

嘗試composer dump-autoload

〜問候

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM