0

현재 수행하려는 작업은 단위 테스트에서 클래스의 생성자를 테스트하는 것입니다.신 개체, 테스트 유형, 테스트 적용 범위 및 클래스를 단위 테스트 가능하게 만드는 방법

이 개체의 인스턴스가 "신의 개체"인지 여부는 확실치 않지만 여러 다른 구성 요소 만 집계하기 때문에 그렇다고 말할 수 있습니다.

어느 쪽이든, 나는 더 나은 디자인에 열려 있습니다.

그래서 거친 클래스 다이어그램은 의심 신 클래스입니다이

enter image description here

World 것 같습니다. 종속물 인 ServiceProvider, CommandRegistry, EventHubEnvironment은 생성자를 통해 주입됩니다. 생성자에서

, World는 다음과 같은 작업을 수행합니다 private 필드에

  1. 저장 종속성을
  2. 한 후크 world를 통해 모든 명령에 대한 통지를하지 실행되는 수신되도록 eventHub($this, 'onCommandIssued') 등록 world 인스턴스 자체 (도 방법이 executeCommand 임)
  3. 세계 : $this->environment->adoptWorld($this). 환경의 역할은 실행 환경의 일부 현실 세계에 적응하는 것입니다. 예를 들어 웹 환경에는 콘솔 응용 프로그램 환경 (예 : "세션"서비스)에서 사용할 수없는 특정 서비스가 있습니다.
  4. 세계의 건설이 끝난 이벤트 허브 : $this->eventHub->notify(new WorldConstructedEvent($this));

아마 이것은 무거운 생성자처럼 보일지 모르지만 단순히 "세상을 구축하는 것"으로 정의 된 것입니다.

World은 기본적으로 다른 서비스가 후크를 등록 할 수있는 명령어 (데이터 전송 객체, World::executeCommand())를 보내는 게이트웨이입니다. 문제/질문에 이제

:

  1. 나는이 생성자 단위 테스트에 노력하고 있어요,하지만 난 그게 아무것도하지만, 단위 테스트 같은 느낌 @uses 주석의 무리를 추가해야합니다. 그렇다면 기능 테스트는 무엇입니까? 유닛 테스트 World은 어색하며, 다른 테스트는 정말 쉽지 않습니다. 다른 테스트에서이 문제가 나타나지 않습니다. 왜 그런지, 그리고 디자인을 개선하는 방법에 대해 스스로에게 묻습니다.
  2. World은 신 개체입니까? 모든 작업은 다른 구성 요소를 집계하여 호출을 전달하는 것뿐입니다.
  3. World의 방법을 제대로 단위 테스트하는 방법은 무엇입니까? 많은 스텁을 사용하고 종속성을 주입하면 여전히 단위 테스트가 수행됩니까?

이것은 도메인 기반 설계 (복잡한) 응용 프로그램을위한 것이며, 설계를 더 잘 (테스트 가능하고 분리 된) 제안 할 수 있도록 제안합니다.

자세한 내용이 필요하면 의견서에 알려주십시오.

이 토론이 어디로 이어질 지 모르겠으므로 제 질문을 수정할 수 있습니다.

+1

난 당신이 모의 EventHub을 공급하고 후크 메소드가 호출되어 있는지 확인 것이라고 생각합니다. 다른 종속성에 대해 필요한만큼 반복하십시오. 나는 당신 질문에 뭔가 빠져 있다고 생각합니다. – Cerad

+0

당신은 스텁'EventHub'을 의미합니다, 맞습니까? 테스트 된 클래스는'World'이므로 내 경우에는 이것이 유일한 모방이 될 것입니다. – Flavius

+0

어쨌든 고마워, 좋은 생각이야. – Flavius

답변

0

드디어 단위 테스트에 적절한 기대치를 설정하여 클래스를 가지고와 종속성을 조롱 :

<?php 

namespace Common\World; 

use TestFramework\TestCase; 

class WorldTest extends TestCase 
{ 
    /** 
    * @test 
    * @covers \Common\World\World::__construct 
    * @uses \Common\World\World::setEventHub 
    * @uses \Common\World\Event\Adopted 
    */ 
    public function construction() 
    { 
     /** @var \Common\World\Environment $environmentStub |\PHPUnit_Framework_MockObject_MockObject */ 
     $environmentStub = $this->getMockBuilder('Common\World\Environment')->getMock(); 
     /** @var \Common\World\EventHub|\PHPUnit_Framework_MockObject_MockObject $eventHubStub */ 
     $eventHubStub = $this->getMock('Common\World\EventHub'); 

     $environmentStub->expects($this->once()) 
      ->method('adoptWorld') 
      ->will($this->returnCallback(function (World $world) use ($eventHubStub) { 
       $world->setEventHub($eventHubStub); 
       return true; 
      })); 
     $eventHubStub->expects($this->once()) 
      ->method('trigger') 
      ->with($this->isInstanceOf('Common\World\Event\Adopted')); 
     $this->assertInstanceOf('Common\World\World', new World($environmentStub)); 
    } 

    /** 
    * @test 
    * @covers \Common\World\World::__construct 
    * @expectedException \RuntimeException 
    * @expectedExceptionMessage the environment has rejected this world for incompatibility reasons 
    */ 
    public function construction_rejected() 
    { 
     /** @var \Common\World\Environment $environmentStub */ 
     $environmentStub = $this->getMockBuilder('Common\World\Environment')->getMock(); 
     $environmentStub->expects($this->once()) 
      ->method('adoptWorld') 
      ->will($this->returnValue(false)); 

     new World($environmentStub); 
    } 


}