zoukankan      html  css  js  c++  java
  • Laravel 测试教程

    参考链接:https://laravel-news.com/seeding-data-testing

    迁移文件

    修改 database/migrations/2014_10_12_000000_create_users_table.php

    class CreateUsersTable extends Migration
    {
        /**
         * Run the migrations.
         *
         * @return void
         */
        public function up()
        {
            Schema::create('users', function (Blueprint $table) {
                $table->increments('id');
                $table->string('name');
                $table->string('email')->unique();
                $table->string('password');
                $table->rememberToken();
                $table->timestamps();
            });
    
            // following table is storing the relationship between users
            // user_id is following follow_user_id
            Schema::create('following', function (Blueprint $table) {
                $table->integer('user_id')->unsigned()->index();
                $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
    
                $table->integer('follow_user_id')->unsigned()->index();
                $table->foreign('follow_user_id')->references('id')->on('users')->onDelete('cascade');
    
                $table->timestamps();
            });
        }
    
        /**
         * Reverse the migrations.
         *
         * @return void
         */
        public function down()
        {
            Schema::dropIfExists('following');
            Schema::dropIfExists('users');
        }
    }
    

    执行迁移

    php artisan migrate
    Migration table created successfully.
    Migrated: 2014_10_12_000000_create_users_table
    Migrated: 2014_10_12_100000_create_password_resets_table
    

    User Model

    修改 app/User.php

    class User extends Authenticatable
    {
        use Notifiable;
    
        /**
         * The attributes that are mass assignable.
         *
         * @var array
         */
        protected $fillable = [
            'name', 'email', 'password',
        ];
    
        /**
         * The attributes that should be hidden for arrays.
         *
         * @var array
         */
        protected $hidden = [
            'password', 'remember_token',
        ];
    
        public function follows(User $user)
        {
            $this->following()->attach($user->id);
        }
    
        public function unfollows(User $user)
        {
            $this->following()->detach($user->id);
        }
    
        public function following()
        {
            return $this->belongsToMany('AppUser', 'following', 'user_id', 'follow_user_id')->withTimestamps();
        }
    
        public function isFollowing(User $user)
        {
            return !is_null($this->following()->where('follow_user_id', $user->id)->first());
        }
    }
    

    这里使用了多对多用户关系关联方法[1]

    种子文件

    创建一个种子文件 database/seeds/UsersTableSeeder.php

    php artisan make:seeder UsersTableSeeder
    

    在种子文件中使用工厂方法[2]

    use AppUser;
    use IlluminateDatabaseSeeder;
    
    class UsersTableSeeder extends Seeder
    {
        /**
         * Run the database seeds.
         *
         * @return void
         */
        public function run()
        {
            $users = factory(User::class, 10)->create();
        }
    }
    

    执行种子文件

    1. 方式一
    php artisan db:seed --class=UsersTableSeeder
    
    1. 方式二

    database/seeds/DatabaseSeeder.php 中注册种子文件

    class DatabaseSeeder extends Seeder
    {
        /**
         * Run the database seeds.
         *
         * @return void
         */
        public function run()
        {
            $this->call(UsersTableSeeder::class);
        }
    }
    

    执行这个 DatabaseSeeder 这个大种子。

    php artisan db:seed
    

    测试用例

    创建一个测试用例。

    php artisan make:test FeatureUserTest
    

    修改 tests/Feature/UserTest.php 的内容。

    use AppUser;
    
    class UserTest extends TestCase
    {
        public function test_have_10_users()
        {
            $this->assertEquals(10, User::count());
        }
    }
    

    执行测试

    vendorinphpunit
    

    完整的测试文件

    <?php
    
    use AppUser;
    use IlluminateFoundationTestingWithoutMiddleware;
    use IlluminateFoundationTestingDatabaseMigrations;
    use IlluminateFoundationTestingDatabaseTransactions;
    
    class UserTest extends TestCase
    {
    
        use DatabaseTransactions;
    
        public function test_follows()
        {
            $userA = User::find(2);
            $userB = User::find(3);
    
            $userA->follows($userB);
    
            $this->assertEquals(1, $userA->following()->count());
        }
    
        public function test_unfollows()
        {
            $userA = User::find(3);
            $userB = User::find(2);
    
            $userA->unfollows($userB);
    
            $this->assertEquals(0, $userA->following()->count());
        }
    
        public function test_A_follows_B_and_C()
        {
            $userA = User::find(1);
    
            $ids = collect([2, 3, 4, 5, 6, 7, 8, 9, 10]);
            $random_ids = $ids->random(2);
    
            $userB = User::find($random_ids->pop());
            $userC = User::find($random_ids->pop());
    
            $userA->follows($userB);
            $userA->follows($userC);
    
            $this->assertEquals(2, $userA->following()->count());
        }
    }
    

    每执行一次测试,都会在数据库表中插入数据。因此这一次运行结果和前一次可能不一样

    我们不得不像下面这样,每执行一次测试,就得重新 refresh & seeding吗?

    php artisan migrate:refresh --seed
    vendorinphpunit
    

    不用!加上 DatabaseTransactions 就好了。

    class UserTest extends TestCase
    {
        use DatabaseTransactions;
    
        ...
    }
    

    这个 Trait 将所有测试项放在一个事务中。无论执行结果如何(全部成功或者没全部成功)都不会对之前的数据库数据造成任何影响,也就是说这个事务在最后总是回滚

    tags: Laravel 项目

    1. belongsToMany 方法用来定义多对多关系。它的第一个参数是关联表(这里是自关联,用户关注用户);第二个参数是中间表名(这里定义为 following);第三个参数是 $this 指代的 Model 的主键在中间表里的字段名;第四个参数是对应表(这里指被关注的人,对应的还是 users 表)的主键在中间表里的字段名。 ↩︎

    2. 工厂方法在 database/factories 下定义,可以定义在 ModelFactory.php 中,也可以定义在基于 Model 的工厂方法里(比如 UserFactory.php)。它们都会被 Laravel 处理。 ↩︎

  • 相关阅读:
    汉罗塔
    汉罗塔动画实现
    画五星红旗
    科学与可视化
    类和正则表达式
    圆周率
    汉诺塔
    jieba库
    Python图片处理
    随手笔记
  • 原文地址:https://www.cnblogs.com/zhangbao/p/6813854.html
Copyright © 2011-2022 走看看