使用Model Factories

时间:2016-04-04 13:02:09

标签: php mysql laravel eloquent laravel-5.2

我在测试类的方法中生成了一个非常小的数据集,我曾尝试在setUp()方法中生成数据,但是每次测试都会导致锁定等待超时。将此代码移出setUp()方法并将其置于其自己的方法中有所帮助。这意味着不是每个测试都抱怨锁。

我正在使用Laravel 5.2中的DatabaseTransactions特性,以便在每个测试用例运行之前重置数据库。

在我遇到的每个测试用例中,我都会调用这样的模拟数据。

$data = self::getRandomCommunityWithAssociatedData();

实际方法仅为创建的社区生成一些社区对象和用户对象。

public static function getRandomCommunityWithAssociatedData()
{
    self::$communities = factory(\Community::class, self::COMMUNITIES_TO_CREATE)->create()->each(function ($community) {
        self::$users[$community->id] = factory(User::class, self::USERS_TO_CREATE)->create()->each(function (\User $user) use ($community) {
            $user->community()->associate($community);
        });

        self::$admins[$community->id] = factory(User::class, 'superadmin', self::ADMINS_TO_CREATE)->create()->each(function (\User $admin) use ($community) {
            $admin->community()->associate($community);
        });
    });

    $community = self::$communities[mt_rand(0, count(self::$communities) - 1)];

    return ['community' => $community, 'users' => self::$users[$community->id], 'admins' => self::$admins[$community->id]];
}

该方法中使用了一些常量,它们用于确定要创建的每个对象的数量。目前,我正在为每个社区实例创建2个社区,3个用户和2个管理员。

锁定等待超时是不可预测的,一次运行可能发生在第一个测试用例上,另一次运行可能发生在第五个测试用例上。

我试图将MySQL等待锁定的时间增加到500秒,而我仍然会收到超时。增加这个时间确实不是一个选择,因为测试需要能够在所有环境中运行。

在Laravel 5.2中使用如此小的数据集的DatabaseTransactions特性时,为什么我可能会获得这些锁定等待超时的任何想法?

1) UserEmailNotificationsTest::testActiveAdminReceivesNewCommentEmailNotification
Illuminate\Database\QueryException: SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded; try restarting transaction (SQL: insert into `communities` (`

上面执行的查询是社区表上的一个简单插入,并且没有复杂的子查询或此类数据生成中发生的类似事件。

启用查询日志,结果。

       30 Query START TRANSACTION
       30 Query SAVEPOINT trans2
       30 Prepare   insert into `communities` (`viddler_id`, `domain`, `subdomain`, `active`, `max_seats`, `created_at`, `updated_at`, `assignment_seats`, `general_settings`, `access_settings`, `branding_settings`) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
       30 Execute   insert into `communities` (`viddler_id`, `domain`, `subdomain`, `active`, `max_seats`, `created_at`, `updated_at`, `assignment_seats`, `general_settings`, `access_settings`, `branding_settings`) values ('74', 'gaylord.com', 'qui', '1', '24', '2016-03-30 16:25:45', '2016-04-04 02:27:04', '23', 'a:11:{s:5:\"title\";s:0:\"\";s:11:\"description\";s:0:\"\";s:10:\"meta_title\";s:0:\"\";s:16:\"meta_description\";s:0:\"\";s:13:\"meta_keywords\";s:0:\"\";s:17:\"thumbnail_display\";s:0:\"\";s:18:\"group_nomenclature\";s:8:\"Channels\";s:13:\"home_template\";s:0:\"\";s:11:\"api_version\";s:1:\"2\";s:8:\"language\";s:2:\"en\";s:21:\"use_nested_navigation\";i:0;}', 'a:10:{s:12:\"restrictions\";s:10:\"Restricted\";s:17:\"auto_registration\";i:0;s:14:\"default_active\";i:0;s:12:\"oauth_google\";i:0;s:14:\"oauth_facebook\";i:0;s:14:\"oauth_linkedin\";i:0;s:16:\"oauth_reg_google\";i:0;s:18:\"oauth_reg_facebook\";i:0;s:18:\"oauth_reg_linkedin\";i:0;s:11:\"lti_enabled\";i:0;}', 'a:14:{s:13:\"contact_email\";s:0:\"\";s:17:\"contact_link_text\";s:0:\"\";s:9:\"logo_file\";s:0:\"\";s:14:\"carousel_items\";s:0:\"\";s:11:\"html_header\";s:0:\"\";s:16:\"footer_copyright\";s:45:\"© 2015 Viddler Inc. All Rights Reserved.\";s:19:\"footer_privacy_link\";s:37:\"http://www.viddler.com/privacy-policy\";s:17:\"footer_terms_link\";s:35:\"http://www.viddler.com/terms-of-use\";s:14:\"help_link_text\";s:4:\"Help\";s:9:\"help_link\";s:0:\"\";s:7:\"color_1\";s:7:\"#ffffff\";s:7:\"color_2\";s:7:\"#2C333C\";s:7:\"color_3\";s:7:\"#2C333C\";s:7:\"color_4\";s:7:\"#60a1d7\";}')
160404  9:30:25    30 Close stmt
       21 Query ROLLBACK
       21 Quit
       22 Query ROLLBACK
       22 Quit
       23 Query ROLLBACK
       23 Quit
       24 Query ROLLBACK
       24 Quit
       25 Query ROLLBACK
       25 Quit
       26 Query ROLLBACK
       26 Quit
       27 Query ROLLBACK
       27 Quit
       28 Query ROLLBACK
       28 Quit
       29 Query ROLLBACK
       29 Quit
       30 Query ROLLBACK
       30 Quit

1 个答案:

答案 0 :(得分:2)

因此,增加锁定等待超时不是最佳做法; the best practice is to catch the error and recover

正式地说,这就是你应该做的事情:

  

繁忙的服务器上的死锁和锁定等待超时都是正常的   应用程序必须才能意识到它们可能会发生   通过重试来处理它们。你可以通过做出来减少它们的可能性   在第一次更改数据之间尽可能少地工作   事务和提交,因此锁保持最短   可能的时间和尽可能少的行数。的有时   不同交易之间的分工可能是实际的   有帮助的。