2013-08-10 5 views
2

데이터베이스 연결을 관리하는 클래스에서 TDD를 사용하려고합니다. 그러나인스턴스 조롱 및 암시 적 생성자

  • 나는 종종
  • 난 그냥도 SQLite는 :memory:로, 실제 연결에 대한 클래스없는 혼란을 테스트 할
  • 내가 연결을 테스트 할 수있는 데이터베이스가 사용할 수있는 네트워크에서 멀리 개발하고 플랫폼 독립적 인 방식 (예 : MySQLi 객체 용 PDO 객체 교환 등). 특히 데이터베이스가 모두 MySQL이 아니기 때문에 일부는 SQLServer입니다.

는 기본적으로 나는이 작업을 수행 할 수 :

class ConnectionManager { 
    ... 
    public function getConnection($name) { 
     $params = $this->lookup($name); 
     return new \PDO($params['spec'], $params['username'], $params['password']); 
    } 
} 

그리고 내 테스트 러너에

:
class ConnectionManagerTest extends \PHPUnit_Framework_TestCase { 
    public function testGetConnection() { 
     $cxn = new ConnectionManager(); 
     $this->assertNotNull($cxn->getConnection('test')); // or whatever 
    } 
} 

은 어떻게 든 내가 PDO 클래스의 모의를 사용하고 싶습니다. 명시 적 매개 변수를 테스트 클래스 생성자 또는 메서드 중 하나에 추가하는 유일한 방법은 무엇입니까? 나는 Mockery 문서에 따라 '인스턴스 조롱 (mocking)'을 시도했지만, 자동 로딩을 사용하면 '치명적인 오류는 클래스를 재 선언 할 수 없다'(duh).

나는 테스트에서 순전히 사용 된 코드로 계약을 오염시키지 않기를 원하지만 그게 유일한 방법입니까? 당신의 도움이

+0

연결 관리자는 항상 (항상) 'PDO'를 반환합니다. 이제 테스트가 시작되면 다른 연결 관리자가 먼저 필요할 것입니다. – hakre

+0

사실 PDO가 여러 가지 연결 유형을 지원하기 때문에 연결 관리자 문제는 다소 덜 중요합니다. 주요 문제는 네트워크 외부에서 개발할 때 실제 연결을 사용할 수 없다는 것입니다.그리고 나중에이 '평범한 오래된 PHP 객체'를 프레임 워크에 넣어야 할지도 모르겠지만 어느 것을 알지 못하기 때문에 가능한 구현과 무관 한 사람이되고 싶습니다. – excatholica

+0

글쎄, 나는 이름 때문에 찔렀다. 이 작업이 필요하다면,'ConnectionManagerStub 클래스를 작성하여 ConnectionManager'를 확장 한 다음 테스트 할 필요가있는 클래스를 변경하여 종속성을 없애고 스텁에서 협업을 유지하십시오. PDO를 전혀 사용하지 않는 테스트 (또는 메모리에있는 PDO 또는 PDO를 사용하지 않는 PDO). – hakre

답변

3

의존성 주입 당신을 도울 수있는 경우 모양에 대한

감사합니다. 이 기술을 설명하는 웹 (여기에는 wikipedia overview)에 대한 많은 좋은 기사가 있으며이 이전의 stack overflow answer은 기술에 대한 간결한 설명을 제공합니다 (예는 Java로되어 있지만 패턴을 설명하고 다른 언어로 쉽게 이식 할 수 있어야 함).).

"테스트를 위해 순전히 사용 된 계약서로 코드를 오염시키고 싶지 않다"는 당신의 요지는 흥미 롭습니다. TDD에 대한 더 많은 경험을 얻으면서 쉽게 테스트 할 수 있고 훌륭한 코드를 작성하는 코드 작성은 본질적으로 동일한 동전의 양면입니다. TDD의 미묘한 힘 중 하나 (올바르게 실행 된 경우)는 응용 프로그램으로 쉽게 성장할 수있는 우수한 디자인으로 이끌어줍니다. 코드를 디자인하는 방법의 핵심에 테스트를 적용하는 접근 방식을 따르면 실제로 코드를 클라이언트의 관점에서 설계하므로 코드의 다른 구성 요소에 대한보다 명확한 인터페이스로 이어지고 궁극적으로 이러한 인터페이스를 사용하는 코드를보다 명확하게 만듭니다.

종속성 주입은 TDD 다음에 적용되는 일반적인 기술이며 이러한 점을 잘 보여줍니다. 한편으로는 테스트 시간에 구성 요소를 쉽게 교환 할 수 있으므로 데이터베이스를 호출하거나 구성 요소 간의 상호 작용을 모의하고 검증 할 필요가 없으므로 테스트에 효과적입니다. 그러나 낮은 결합 및 유연한 디자인으로 이끌어주기 때문에 일반적으로 좋은 디자인을 지원합니다 (예를 들어, 데이터베이스에 대한 의존성 삽입 액세스 인 경우 데이터 소스를 데이터베이스에서 다른 스키마로 변경하는 것이 매우 간단합니다. 과학 기술).

+0

DI가 분명히 가능할 수도 있지만 PHP로 구현하는 것은 까다 롭습니다. 일반적으로 [Symfony2] (http://symfony.com/doc/current/components/dependency_injection/index.html) 또는 [Laravel] (http : //four.laravel.)과 같은 IoC 컨테이너 또는 기타 등이있는 프레임 워크가 필요합니다. co.kr/docs/ioc). 나는 트랙 아래로 Laravel을 사용하기를 바라고 있지만 현재는 그것을 고려할 수 없다. 그래서 나는 가능한 한 많이 'POPO'(Plain Old PHP Objects)를 사용하고 있으며, 컨테이너와 프레임 워크를 잡기 전에 TDD로 응용 프로그램이 작동 함을 증명합니다. – excatholica

+0

아마도 데이터 소스 기술을 변경하는 것에 대한 마지막 의견도 관련성이 있습니다. 제가 작업하고있는 플랫폼에는 일부 트랜잭션, 특히 쓰기가 REST 서비스를 통해서만 사용할 수있는 SaaS 구성 요소가 포함되어 있습니다. 코드를 가능한 한 데이터 소스에 독립적으로 유지해야하는 또 다른 이유입니다. – excatholica

+0

아, 흥미 롭습니다. 언어가 너무 다를 것이라는 것을 깨닫지 못했습니다. W.R.T는 IoC 프레임 워크를 사용해야한다. PHP에서 DI를 여러 가지 방법으로 시뮬레이션 할 수있다. 예를 들어, 테스트중인 클래스의 변수에 PDO 개체를 할당 한 다음 [Setter Injection] (http://misko.hevery.com/2009/02/19/constructor-injection-vs-setter)을 사용하면됩니다. -injection /) 테스트 용 모의 버전 삽입 (또는 단순히 변수에 모의 객체 할당) – robjohncox