【问题标题】:PHPUnit - AssertCount fails when having multiple insertion methodsPHPUnit - 具有多种插入方法时,AssertCount 失败
【发布时间】:2021-05-01 01:58:35
【问题描述】:

嘿,我刚开始使用 PHPUnit。我正在尝试测试将模型(称为 Actor)插入数据库。此模型的创建导致创建其他模型(如 SubactorContact)。出于这个原因,我已经单独测试了每个模型的创建。

问题在于,当我尝试单独运行每个测试时,一切正常。但是,当我尝试运行全班测试时。 AssertCount 方法失败,因为每个方法都添加了一个模型,因此计数会增加,并且在运行整个类测试时数据库不会刷新。

我尝试在每个方法开始时初始化每个模型的计数,但我认为这不是最好的解决方案。

谁能帮忙?

谢谢!

class ActorTest extends TestCase
{
    use WithFaker;
    use RefreshDatabase;

    
    /** @test */
    public function an_actor_can_be_added()
    {
        $user = factory(Admin::class)->create();

        $response = $this->actingAs($user)
        ->post('admin/actor',
        array_merge(factory(Actor::class)->make()->toArray(),
        ['contact'=>[factory(Contact::class)->make()->toArray()]]));
        
        $this->assertCount(1, Actor::all());
    }

    /** @test */
    public function a_subactor_is_added_when_actor_created(){
        $user = factory(Admin::class)->create();

        $this->actingAs($user)
        ->post('admin/actor',
        array_merge(factory(Actor::class)->make()->toArray(),
        ['contact'=>[factory(Contact::class)->make()->toArray()]]));

        $this->assertCount(1, Subactor::all());
    }

    /** @test */
    public function a_contact_is_added_when_actor_created(){
        $user = factory(Admin::class)->create();

        $this->actingAs($user)
        ->post('admin/actor',
        array_merge(factory(Actor::class)->make()->toArray(),
        ['contact'=>[factory(Contact::class)->make()->toArray()]]));

        $this->assertCount(1, Contact::all());
    }

    /** @test */
    public function an_actor_is_linked_to_subactor_when_created(){
        $user = factory(Admin::class)->create();

        $this->actingAs($user)
        ->post('admin/actor',
        array_merge(factory(Actor::class)->make()->toArray(),
        ['contact'=>[factory(Contact::class)->make()->toArray()]]));

        $actor = Actor::first();
        $subactor = Subactor::first();
        
        $this->assertEquals($actor->id, $subactor->actor_id); 
    }

    /** @test */
    public function a_subactor_is_linked_to_contact_when_created(){
        $user = factory(Admin::class)->create();

        $this->actingAs($user)
        ->post('admin/actor',
        array_merge(factory(Actor::class)->make()->toArray(),
        ['contact'=>[factory(Contact::class)->make()->toArray()]]));

        $subactor = Subactor::first();
        $contact = Contact::first();
        
        $this->assertEquals($subactor->id, $contact->subactor_id); 
    }
}

【问题讨论】:

    标签: php database laravel unit-testing phpunit


    【解决方案1】:

    我不知道这是否是正确的解决方案,但我这样做了。

    protected function tearDown(): void
         {
             Actor::truncate();
             Subactor::truncate();
             Contact::truncate();
         }
    

    【讨论】:

    • 您是对的,但最好将该代码移至setUp() 方法(一个简单的助记规则是“设置多于拆除”)。理由是tearDown() 通常不能保证执行(由于致命错误或手动停止测试),它可能导致下一次运行失败,这在 CI 管道上尤其痛苦。因此通常的做法是清理setUp()中的状态。
    【解决方案2】:

    您正在测试的代码广泛使用全局状态(通过静态方法),这就是您的测试相互干扰的原因。为避免在每个方法中重置状态,您可以使用带有 @before 注释的方法或覆盖测试用例类的 setUp() 网络 - 这些代码将在每个测试方法之前执行。

    【讨论】:

    • 你的意思是我应该在setUp()方法中刷新数据库?
    • 如果刷新数据库会重置被测系统的状态,并且没有更便宜的方法可以重置状态 - 那么可以。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-27
    • 1970-01-01
    • 2011-09-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多