2017-12-29 21 views
4

팀을 만든 다음 해당 팀을 게임에 추가 한 다음 해당 게임을 이벤트에 추가하려고합니다. 그러나 게임이 생성되면 자동으로 이벤트에 첨부 할 이벤트가 생성됩니다 . 정상적인 상황에서는 괜찮 았지만 첫 번째 경기가 시작된 경우와 비교하여 팀이 합류했는지 테스트 중이므로 특정 날짜의 일정을 만들어야합니다. 게임을 추가하기 위해서는 먼저 게임을 만들어야하기 때문에 이벤트를 먼저 만들 수는 없습니다.테스트가있는 Laravel 모달 팩터

내 논리를 수정하여 게임과 이벤트를 올바르게 만들 수있는 사람이 있습니까?

나는이 엣지 경우를 위해 무엇을해야하는지 모른다.

• 경우

• 팀을 추가로 게임을 추가 이벤트

• 만들기 :

/** @test */ 
public function a_team_with_a_game_after_they_started_the_season_cannot_have_their_joined_at_date_after_their_first_match() 
{ 
    $team = factory(Team::class)->create(['joined_at' => '2017-10-08']); 

    $game = GameFactory::create([], [$team]); 
    $event = EventFactory::create(['date' => '2017-10-09'], null, $game); 

    $validator = new BeforeFirstGameDate($team); 

    $this->assertFalse($validator->passes('joined_at', '2017-10-10')); 
    $this->assertEquals('The joined at date cannot be AFTER the team\'s first game.', $validator->message()); 
} 

Factories 

<?php 

use App\Models\Game; 
use App\Models\Team; 

class GameFactory 
{ 
    public static function create($overrides = [], $teams = []) 
    { 
     $match = factory(Game::class)->create($overrides); 

     self::addTeamsForGame($teams, $game); 

     return $game; 
    } 

    /** 
    * @param $teams 
    * @param $game 
    */ 
    public static function addTeamsForGame($teams, $game) 
    { 
     $teamsForGame = []; 

     $numberOfTeamsToAdd = $numberOfTeams - count($teams); 

     if ($numberOfTeamsToAdd) { 
      $teamsForMatch = factory(Team::class, $numberOfTeamsToAdd)->create(); 
      array_push($teams, $teamsForGame); 
     } else { 
      array_push($teams, $teamsForGame); 
     } 

     $match->addTeams($teamsForGame); 
    } 
} 


<?php 

use App\Models\Event; 

class EventFactory 
{ 
    public static function create($overrides = [], $totalNumberOfGames = 8, $games = []) 
    { 
     $event = factory(Event::class)->create($overrides); 

     $numberOfGamesToAdd = $totalNumberOfGames - count($games); 
     $gameToStartAt = count($games) + 1; 

     foreach (array_wrap($games) as $game) { 
      $game->addToEvent($event); 
     } 

     for ($gameNumber = $gameToStartAt; $gameNumber <= $numberOfGamesToAdd; $gameNumber++) { 
      GameFactory::create(['event_id' => $event->id, 'game_number' => $gameNumber]); 
     } 

     return $event; 
    } 
} 


$factory->define(App\Models\Game::class, function (Faker\Generator $faker) { 
    static $order = 1; 
    return [ 
     'event_id' => function() { 
      return factory(App\Models\Event::class)->create()->id; 
     }, 
     'game_number' => $order++, 

    ]; 
}); 

$factory->define(App\Models\Event::class, function (Faker\Generator $faker) { 
    $name = $faker->sentence; 
    return [ 
     'name' => $name, 
     'slug' => str_slug($name), 
     'date' => $faker->dateTimeBetween('-10 years'), 
    ]; 
}); 

답변

2

참고 : 아래 소스 코드는 원래의 질문에 Event, GameTeam과 같은 모델의 특정 구현이 주어지지 않았기 때문에 일부 가정을 기반으로합니다. 질의에 소스가 포함 된 Git 저장소를 추가하여 구현을보다 자세히 반영한 구체적인 답변을 얻는 것이 좋습니다.

먼저 테스트 일부 총론 : (여기서 코드 표시 위에서 에 초점을 맞춘 하나)

  • 단위 테스트해야 도메인 층의 테스트 한 특정 양태 따라서 BeforeFirstGameDate이 제대로 작동하지만 관련 재구성 서비스 (데이터베이스) 또는 개체 재구성을위한 팩터 리를 테스트하지 않도록하기 위해 사용되는 기술은 "모의"또는 "예언"
  • 통합 테스트입니다. 위의 코드는) 다른 한쪽에 있어야합니다. 실제 구현으로 테스트 할 수 있지만 (가능한 경우 "mocks"또는 "prophecies"없음) 위조/제공된 시나리오에서 - 공장, 모델 및 유효성 검사기의 전체 응용 프로그램을 테스트하려면 전체 테스트 시나리오를 제공해야합니다 테스트 하나의 분리 된 단위에 국한 - 그리고 예를 들어 데이터베이스에하는 단계와 "단위 테스트"의 장치에 대한 자세한 부분을 초점을 두는되고 이들

에 따라 테스트를 수행하여 테스트처럼 보일 수 있습니다 그리고 이들의 조합은 아닙니다 :

/** @test */ 
public function eventIsCreated() 
{ 
    ... 
    static::assertSame($expectedEvent, EventFactory::create(...)); 
} 
/** @test */ 
public function teamIsCreated() 
{ 
    ... 
    static::assertSame($expectedTeam, TeamFactory::create(...)); 
} 
/** @test */ 
public function gameIsCreated() 
{ 
    ... 
    static::assertSame($expectedGame, GameFactory::create(...)); 
} 
/** @test */ 
public function beforeFirstGameDateValidatorRejectsLateApplications() 
{ 
    ... 
} 

BeforeFirstGameDate 유효한 테스트 케이스

/** 
* @test 
*/ 
public function beforeFirstGameDateValidatorRejectsLateApplications() 
{ 
    $event = $this->prophesize(Event::class); 
    $game = $this->prophesize(Game::class); 
    $team = $this->prophesize(Team::class); 

    $event->getGames()->willReturn([$game->reveal()]); 
    $game->getTeams()->willReturn([$team->reveal()]); 
    $team->get('joined_at')->willReturn('2017-10-08'); 

    $subject = new BeforeFirstGameDate($team->reveal()); 

    static::assertFalse(
     $subject->passes('joined_at', '2017-10-10') 
    ); 
} 

이을 (필기 시험에서 일반적으로 가장 좋은 방법) 테스트 할 대상이 무엇을, $subject로 이름 테스트 할 인스턴스를 분명히하기 위해 - ATION는 예언을 사용하고 다음과 같이 보일 수 있습니다 귀하의 Event, GameTeam 모델은 더 이상 공장 구현에 의존하지 않지만 예언을 사용하여 속성 및 동작을 시뮬레이션합니다. 따라서 공장이 변경되거나 리팩터링되는 경우 객체 재검토를 주장하는 테스트 만 조정하면됩니다. 예를 들어 beforeFirstGameDateValidatorRejectsLateApplications은 이러한 팩토리에 대해 크게 의존하지 않으므로 생략 할 수 있습니다. 처음에 언급 한 바와 같이

Event, GameTeam의 메서드와 속성은 실제 구현이이 답을 작성하는 시점에서 알 수없는 때부터 바로 가정입니다.

참고 :

2

당신은 당신이 당신의 응용 프로그램에서이 작업을 수행 할 때와 같은 논리를 사용한다 게임에

날짜를 테스트해야한다면 다음을 수정하십시오.

+0

내가 먼저 이벤트를 만들 경우 그때 이벤트에 추가로에 전달하기 위해 만든 게임을하지 않을 것입니다. – user3732216

+0

앱의 워크 플로 란 무엇입니까? –

+0

이벤트가 생성되면 팀은 이벤트에 할당 된 게임에 할당됩니다. – user3732216