使用Laravel进行适当的测试流程?

4
我正在使用Laravel为IOS应用程序构建API。在使用PHPUnit和内置的Laravel测试时,我遇到了严重的问题,无法测试Web应用程序。
我的流程是:1.用户拥有一个账户;2.用户需要进行身份验证才能执行任何操作。
假设我有一组用户,并且一个用户(所有者)可以管理属于他们其中一个组的成员。我想测试用户将其他成员添加到其组的能力。
我有一个名为testAddGroupMemberPass()的测试方法,它应该...
  1. create a user (owner)
  2. create a group and assign the owner
  3. create a user to add to the group
  4. assert that the owner has the ability to add that member.

    public function testAddGroupMemberPass()
    {
        // 1. create owner
        $owner = factory(User::class)->create();
        $token = JWTAuth::fromUser($owner);
    
        // 2. create group and attach user
        $group = new Group;
        $group->owner_id = $owner->id;
        $group->save();
    
        // 3. create the member to be
        $user = factory(User::class)->create();
    
        // 4. attempt attach the member to the group
        $this->edit('/groups/' . $group->id . '/add-member/' . $user->username . '?token=' . $token)
        ->seeJson(['success' => true]);
    }
    
为了确认一个所有者能够添加用户,您首先需要创建所有者,其次创建组,第三步创建您想要添加到该组的用户,最后才能尝试向API发送请求以实际添加该用户。
问题在于,在前3个步骤中可能会遇到各种与添加成员到组无关的问题,例如用户名和电子邮件唯一性约束。
那么我的当前方法有什么问题?我一直被告知测试应该完全独立于彼此,因此尝试使用之前测试生成的用户和组是没有意义的。
1个回答

0

你可以将123抽象成一个基础测试类,并在测试特定功能的测试中使用相同的方法。

例如:

// TestCase.php
protected function createOwner()
{
    return factory(User::class)->create();
}

protected function createGroup($owner)
{
    // You didn't show this as a factory, but I figured you might want that
    $group = factory(Group::class)->create();
    $group->owner()->associate($owner);
    $group->save();

    return $group;
}

protected function createUser()
{
    return factory(User::class)->create();
}

// In the file you mention above (should be extending TestCase.php)
public function testAddGroupMemberPass()
{
    // 1. create owner
    $owner = $this->createOwner();
    $token = JWTAuth::fromUser($owner);

    // 2. create group and attach user
    $group = $this->createGroup($owner);

    // 3. create the member to be
    $user = $this->createUser();

    // 4. attempt attach the member to the group
    $this->edit('/groups/' . $group->id . '/add-member/' . $user->username . '?token=' . $token)
         ->seeJson(['success' => true]);
}

这些方法可以在其他测试中使用,如下所示:

// In UserTest.php (also extends TestCase.php)
public function testItCreatesAUser()
{
    $user = $this->createUser();

    $this->seeInDatabase('users', $user);
}

事实上,如果您需要让您的世界看起来某种方式,并且正在进行某种功能或集成测试,则需要将该逻辑封装在某个地方。将其移动到基类中将有助于消除重复功能。

在Laravel中,使用Illuminate\Foundation\Testing\DatabaseTransactions特性来处理。每个测试后都会执行一个Rollback。https://laravel.com/docs/5.1/testing#resetting-the-database-after-each-test - tptcat
这应该有助于进一步解释问题...我已经在TestFile中包含了使用DatabaseTransaction trait,并且正在扩展TestCase。 - kyle
我能看到你的整个测试文件并且发布TestCase.php吗?你使用的是哪个版本的Laravel?它肯定会在每个测试之后执行回滚。 - tptcat
不确定这是否是打字错误,但您必须在类声明内部“使用”Trait。在“GroupControllerTest.php”的第12行之后添加以下内容:“use DatabaseTransactions;” - tptcat
已经移除了为调试目的而添加的内容。使用事务将导致出现以下错误,该错误在此代码片段中有所说明... https://gist.github.com/kyle-mccarthy/ca835eef584e96531f32编辑:请注意,使用事务将导致所有测试失败。 - kyle
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接