Laravel 5单元测试 - 在null

时间:2017-02-28 15:26:28

标签: php unit-testing eloquent phpunit laravel-5.4

我尝试为我的UserShop模型之间的关系创建单元测试,但是当我运行vendor\\bin\\phpunit时会抛出此错误,我不知道这个因为我是单位测试的新手。我试图在我的控制器上运行我的代码以查看关系是否真的有效,幸运的是它按预期工作,但在phpunit中运行时却没有。对于这个不使用Models的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); - 此代码在我的示例路由或控制器中运行时实际有效,但在errors

中运行时抛出phpunit

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

非常感谢任何帮助。谢谢!

7 个答案:

答案 0 :(得分:18)

另一个原因

检查测试类是否在扩展使用Tests \ TestCase; ,而不是使用PHPUnit \ Framework \ TestCase;

Laravel随以后一起提供,但是 Tests \ TestCase 类负责设置应用程序,否则,如果模型扩展了 PHPunit \ Framework \,则模型将无法与数据库进行通信。 TestCase

答案 1 :(得分:16)

首先,在每次测试之前调用setUp(),因此你不应该在构造函数中调用它

其次,你应该调用setUp()中的parent :: setUp()来初始化app实例。

答案 2 :(得分:6)

一个解决方案 在文件中应该代替

使用 PHPunit\Framework\TestCase

把这个

使用 Tests\TestCase

答案 3 :(得分:5)

示例:

<?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 :(得分:1)

您正在为两家商店分配ID“2”。

分配不应该是必要的,因为我假设shop table id字段是一个自动增量字段。

另请查看database factories in the Laravel docs,它会为您简化操作。

答案 5 :(得分:0)

问题原因:您无法使用UserTest类的构造函数中调用的代码使用Laravel Models功能-即使将代码放在方法“ setUp”中,也不必要地调用了它来自构造函数。 phpUnit调用SetUp,而无需在构造函数中进行设置。

运行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([....

答案 6 :(得分:0)

当您尝试从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...
}