2012-02-26 5 views
3

젠드 프레임 워크와 PHPUnit을 처음 사용했습니다. 레거시 애플리케이션을 MVC 아키텍처로 변환하고 단위 테스트를 작성하려고합니다. 나는 단위 테스트 개념에 다소 익숙하지만 일반적으로 스터 빙과 조롱으로 붙어있다. 예를 들어, 다음을 고려하십시오.젠드 프레임 워크 애플리케이션에서 PHPUnit 스텁 및 조롱

컨트롤러 조치에서 회원 ID를 전달했는지 테스트하려고합니다. 그런 다음 ID를 사용하여 멤버 개체를 초기화합니다. 그런 다음 멤버 개체와 관련된 여러 메서드를 호출하고 반환 값을 뷰 개체에 할당합니다.

class A extends Zend_Controller_Action { 
    public function viewAction() { 
     $member = new Member($this->getRequest()-> getParam('id')); 

     //perform various calls on the member object 

     $gender = $member->getGender(); 
     ... 

     //assign the return values to the view object 

     $this->view->assign('gender',$gender); 
     ... 

    } 
} 

테스트에서 $ member 변수를 모의 해 메소드 반환 값을 사용자 정의 할 수 있습니까?

여기 내 이해가 잘못된 경우 몇 가지 지침을 크게 부탁드립니다.

감사합니다.

+2

@markus가 아래에 말하는 것 이외에; 이것이 내가 단위 테스트 컨트롤러를 중단 한 이유이며 가능한 많은 로직을 제 모델로 옮겨야했습니다. 결과적으로 필자는 현재 매우 마른 컨트롤러와 매우 뚱뚱한 모델을 사용하여 코드를 개선하고 드라이 클리닝을 유지합니다. – vascowhite

+0

그게 내가하려고하는 일입니다. 이 경우 컨트롤러를 테스트하지 않아도됩니까? (모델에서 결과를 얻고 뷰 변수에 할당하는 것으로 가정합니다.) – Satyam

+0

네, 좋은 점, 린 컨트롤러가 목표입니다! 나는 그것을 내 대답에 포함시킬 것이다. – markus

답변

6

정확하게 이해한다면이 동작에 대한 테스트를 작성하고있는 것입니다. 이 경우 새 인스턴스가 메서드 내부에 만들어 졌기 때문에 $ member를 모의하는 것은 불가능합니다. 그래서 우리는 최대한 많은 객체 다이어그램 (DI)에서 멀리까지 많은 new 문을 띄우려고 노력하고 있습니다.

일반적으로 특별한 PHPunit 테스트 케이스 Zend_Test_PHPUnit이 컨트롤러를 테스트합니다.

그러나 사실 ZF 컨트롤러를 올바르게 테스트하는 것은 매우 어렵거나 불가능합니다 (완전 분리를 의미 함). 나머지 응용 프로그램이나 일반 라이브러리 등을 테스트하는 것이 좋습니다.

즉, ZF1 논리에서 컨트롤러는 부트 스트랩 이후의 중앙 배선 장소이며, new 문이 전통적으로 사용됩니다. 분명히 주입이 아닌 생성되는 모든 인스턴스가 움직이지 않기 때문에 테스트 할 수없는 상태가됩니다.

@vascowhite가 지적했듯이 린 컨트롤러를 위해 노력하는 것이 일반적으로 좋습니다. 즉, 가능한 한 많은 로직을 모델 레이어로 이동하십시오. 이렇게하면 중복성 (DRY)이 낮아지고 동시에 테스트 가능성이 향상됩니다.

그러나 모델을 부 풀리지 않도록주의하십시오. 어느 시점에서 일부 코드를 추가 구성 요소에 인수로 사용하려고 할 것입니다.

또 하나의 문제는 프론트 컨트롤러를 싱글 톤으로 사용할 수 없다는 것입니다. 그래서 당신은 정말로 그러한 행동을 시험 할 많은 선택권이 없습니다. 유일한 옵션은 멤버 인스턴스를 삽입하거나 레지스트리에서 가져 오는 것입니다 (좋은 아이디어가 아닙니다).

따라서 액션 테스트를 위해 완전히 격리 할 수는 없다는 점을 고려하면 분명합니다. 그러나

ZF2는 테스트하기가 훨씬 쉽습니다.

+0

네, 그게 제가 묻고있는 바로 그 것입니다. 그래서 내가이 권한을 가지고 있는지 확인하기 위해 Front Controller의 getParam() 메소드를 조롱하여 mocked $ 멤버 객체를 반환 할 것을 제안 하시겠습니까? 내가 생각한 것을 명확히 해 주셔서 감사하지만 그것을 확인하는 많은 문헌을 찾을 수 없었습니다. – Satyam

+0

사실, 전 프론트 컨트롤러 조롱에 대해서도 틀 렸습니다. 그것은 싱글 톤 (singleton)이고 또 다른 테스트 가능성 방지 패턴입니다. 내 변경된 답변을 참조하십시오. – markus

+0

나는 레지스트리를 한순간에 사용하고 있었지만 시험 문제 때문에 그걸 포기했다. 내가 $ member 변수를 매개 변수로 액션에 전달해야 함을 의미합니까? $ member 객체를 생성하라는 요청에서 멤버 ID가 필요하기 때문에 가능하지 않다고 생각합니다. – Satyam

1

기능 테스트를 통해 컨트롤러를 다루는 것이 좋습니다. 이 경우 조롱 문제를 무시하고 더 나은 테스트 커버리지를 얻을 수 있습니다. 컨트롤러는 강하게 연결되어 있기 때문에 단위 테스트로 항상 다루기가 어렵습니다.

는 ZF와 기능 테스트가 Codeception 사용을 고려 작성하려면 : 몇 가지 예제가 http://codeception.com/01-27-2012/bdd-with-zend-framework.html 또한

, 컨트롤러에 대한 단위 테스트를 할 수있는 방법.그러나, 진실하게, 나는 그들을위한 기능 테스트가 만들어진 후에 단위 테스팅 컨트롤러를 추천한다.

http://codeception.com/docs/06-UnitTestsAndBDD#TestingController

+0

당신은 포기를 잊어 버렸습니다! – markus