2011-11-21 4 views
5

사용자 프로필을 편집 할 수있는 컨트롤러 동작을 테스트하려고합니다. 무엇보다도 나는 기록 된 모든 사용자가 자신의 프로필 만 편집 할 수 있고 다른 프로필은 편집 할 수 없다는 것을 테스트하고 싶습니다. 이 제한을 깨뜨린 경우 작업은 미리 정의 된 홈 페이지로 리디렉션되어야합니다. 이 시나리오와 CakePHP 2에서 AuthComponent를 사용하는 컨트롤러에 대한 단위 테스트를 작성하십시오.

, 나는 ID를 가진 사용자를 생성하는기구가 = 1. 그래서 제한이 방법을 테스트에 생각했다 :

$data = $this->Users->User->read(null, 1); 
$this->Users->Auth->login($data); 
$this->testAction('/users/edit/2', array('method' => 'get')); 
$url = parse_url($this->headers['Location']); 
$this->assertEquals($url['path'], '/homepage'); 

시험이 어설 전달합니다.

$this->testAction('/users/edit/1', array('method' => 'get', 'return' => 'vars')); 
$matcher = array( 
    'tag' => 'form', 
    'ancestor' => array('tag' => 'div'), 
    'descendant' => array('tag' => 'fieldset'), 
); 
$this->assertTag($matcher, $this->vars['content_for_layout'], 'The edition form was not found'); 

그러나이 어설 실패 따라서 다음 단계는 사용자의 로그인 ID를 가지고 '/users/edit/1'을 실행 여부를 확인하는 양식이다. debug()을 조사한 결과 $this->Auth->user()은 전체 정보를 반환하지만 $this->Auth->user('id')null을 반환합니다. 후자를 작업 내에서 비교하여 사용하기 때문에 false로 평가되고 테스트가 실패합니다.

브라우저에서 동작을 테스트 할 때 발생하지만 브라우저에서 동작을 실행하지 않는 것이 흥미로운 점입니다. 그러면이 작업을 테스트하는 올바른 방법은 무엇입니까?

감사합니다.

$this->Auth->user('id') 

다음 중 하나를 시도해보십시오 : 대신

답변

5

실제 정답은 모의 객체를 사용하는 대신 실제로 수동으로 사용자 로그인을해야합니다 :

$this->controller = $this->generate('Users', array(
    'components' => array('Auth' => array('user')) //We mock the Auth Component here 
)); 
$this->controller->Auth->staticExpects($this->once())->method('user') //The method user() 
    ->with('id') //Will be called with first param 'id' 
    ->will($this->returnValue(2)) //And will return something for me 
$this->testAction('/users/edit/2', array('method' => 'get')); 
를 기본적으로이 같은 사용자가 로그인해야

mock을 사용하면 컨트롤러를 테스트하는 가장 쉬운 방법이며 가장 유연한 방법입니다.

업데이트 2015년 3월 11일는

또한 AuthComponent

의 모든 방법
$this->controller = $this->generate('Users', array(
    'components' => array('Auth') // Mock all Auth methods 
)); 
+0

어쨌든'generate()'를 사용해야한다면'ControllerTestCase'를 사용하는 것이 무엇입니까? – elitalon

+0

generate()는 ControllerTestCase에서만 사용할 수 있으며 controller 메소드, 구성 요소, 모델 등을 모의 할 수있는 것과 같이 testAction()을보다 쉽게하기 위해 제공됩니다. generate()를 직접 호출하지 않으면 testAction) CakePHP 디폴트 (_stop() 함수와 redirect() 함수 조롱)로 내부적으로 할 것입니다. –

+0

'generate()'가 실제로 뭔가를했다고 생각했습니다. 이것이 내가 왜'ControllerTestCase'가 기본 설정을 제공했는지를 계속 생각하는 이유입니다. 귀하의 답변을 시도하고 알려 드리겠습니다 :) – elitalon

0

과 같이

$this->Auth->data['User']['id'] 
$this->Session->read('Auth.User.id') 
+0

작동하지 않습니다. 이 방법들이 동등한 의미가 아닌가? – elitalon

0

설정을 :

$this->Users->Session->write('Auth.User', 
    array('id' => 1,'and_other_fields_you_need' => 'whatever') 
); 
0

마크 스토리 나에게 answer in a CakePHP ticket 제공합니다.

$data = $this->Users->User->read(null, 1); 
$this->Users->Auth->login($data['User']); 

대신

$data = $this->Users->User->read(null, 1); 
$this->Users->Auth->login($data); 
1

내가 Jose's answer을 좋아하지만, 비슷한 상황에 직면했을 때 내가 테스트를 만들기 위해 실제 AuthComponent 및 세션을 사용하려면를 조롱 할 수 나에게 확신을 줄거야.

저는 컨트롤러 기반 인증을 사용하고 있습니다. 즉, 앱의 각 컨트롤러는 자체 isAuthorized() 콜백을 제공해야합니다. MyController :: isAuthorized()를 테스트하고 싶다. mock을 사용하여 테스트를 통과하는 것은 너무 쉬운 것처럼 보입니다.

그래서 TestCase :: generate()를 사용하여 mock 구성 요소가있는 모의 컨트롤러를 만드는 대신 Mark Story의 우수 기사 Testing CakePHP Controllers the hard way을 따르고 실제 CakePHP AuthComponent를 사용하여 사용자를 로그인하는 자체 모의 컨트롤러를 제공했습니다.

여기에 my work입니다. testIsAuthorized() 메소드와 맨 위에있는 MockAnnouncementsController 클래스 정의를 참조하십시오.

CakePHP 테스트 프레임 워크에서는 requestAction()을 통해서만 컨트롤러를 테스트하려고한다고 가정합니다. 컨트롤러 안의 Controller :: isAuthorized()와 같은 콜백 구현의 직접적인 단위 테스트를 용이하게하기 위해 설계된 것은 아니며, 이는 AuthComponent와 다른 구성 요소를 조롱하지 않고, 특정 메서드의 테스트에 대한 확신이 떨어지게합니다. 그럼에도 불구하고 이것이 컨트롤러 (예 : "인덱스", "뷰")가 아닌 유닛 테스팅 부분의 유효한 유스 케이스라고 생각하지만 핵심 프레임 워크에서 호출해야하기 때문에 구성 요소에 위임 할 수 없습니다 . 나는 아직도 그것을 어떤 컨트롤러에서도 사용할 수 있도록 추상화 할 수 있을지 생각하고있다.

관련 문제