PHPUnit-AssertCount在具有多个插入方法时失败

PHPUnit-AssertCount在具有多个插入方法时失败,php,database,laravel,unit-testing,phpunit,Php,Database,Laravel,Unit Testing,Phpunit,嘿,我刚开始使用PHPUnit。我正在尝试将模型(称为Actor)插入数据库。创建此模型将导致创建其他模型(如子构件和触点)。因此,我分别测试了每个模型的创建 问题是,当我尝试单独运行每个测试时,一切都正常。但是,当我尝试运行整个类测试时。AssertCount方法失败,因为每个方法都会添加一个模型,因此在运行整个类测试时,计数会增加,并且数据库不会刷新 我试图在每个方法开始时初始化每个模型的计数,但我认为这不是最好的解决方案 有人能帮忙吗 谢谢大家! class ActorTest exte

嘿,我刚开始使用PHPUnit。我正在尝试将模型(称为Actor)插入数据库。创建此模型将导致创建其他模型(如子构件触点)。因此,我分别测试了每个模型的创建

问题是,当我尝试单独运行每个测试时,一切都正常。但是,当我尝试运行整个类测试时。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); 
    }
}

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

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

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

你的意思是我应该在setUp()方法中刷新数据库?如果刷新数据库会重置被测系统的状态,并且没有更便宜的方法重置状态-那么是的。你是对的,但最好将代码移动到
setUp()
方法(简单的助记规则是“设置多于拆卸”)。基本原理是,
tearDown()
通常不能保证执行(由于致命错误或手动停止测试),并且它可能导致下一次运行失败,这在CI管道上尤其痛苦。因此,通常的做法是清除
setUp()
中的状态。