2011-11-21 32 views
5

Tôi đang cố gắng kiểm tra hành động của bộ điều khiển cho phép ấn bản hồ sơ người dùng. Trong số những thứ khác tôi muốn kiểm tra rằng mọi người dùng đã đăng nhập chỉ có thể chỉnh sửa hồ sơ của riêng mình chứ không phải của người khác. Trong trường hợp phá vỡ hạn chế này, hành động phải chuyển hướng đến trang chủ được xác định trước.Viết kiểm tra đơn vị cho bộ điều khiển sử dụng AuthComponent trong CakePHP 2

Với kịch bản này, tôi có một vật cố tạo ra một người dùng với ID = 1. Vì vậy, tôi đã suy nghĩ về thử nghiệm hạn chế theo cách này:

$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'); 

Bài kiểm tra qua khẳng định này. Vì vậy, bước tiếp theo là kiểm tra xem thực '/users/edit/1', trong đó có ID của người dùng đăng nhập, cho thấy các hình thức:

$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'); 

Tuy nhiên khẳng định này không thành công. Sau khi đào bới xung quanh với debug() Tôi đã tìm thấy rằng $this->Auth->user() trả về toàn bộ thông tin nhưng $this->Auth->user('id') trả lại null. Vì tôi sử dụng sau này trong một so sánh trong hành động, nó đánh giá là sai và gây ra các thử nghiệm thất bại.

Điều kỳ lạ là nó xảy ra khi thử nghiệm nhưng không xảy ra khi thực hiện tác vụ trong trình duyệt. Vì vậy, cách chính xác để thử nghiệm hành động này là gì?

Cảm ơn!

Trả lời

5

Câu trả lời đúng thực tế nên sử dụng các đối tượng giả thay vì thực sự đăng nhập người sử dụng trong tay:

$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')); 

Sử dụng mocks là cách dễ dàng nhất để kiểm tra bộ điều khiển và cũng là cách linh hoạt nhất

Cập nhật ngày 11 Tháng Ba 2015

Bạn cũng có thể thử tất cả các phương pháp AuthComponent

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

Vậy thì điểm của việc sử dụng 'ControllerTestCase' là gì nếu bạn phải sử dụng' generate() '? – elitalon

+0

generate() chỉ có sẵn trong ControllerTestCase và nó được cung cấp để làm cho testAction của bạn() dễ dàng hơn, chẳng hạn như có thể giả lập các phương thức điều khiển, các thành phần, mô hình, v.v. Nếu bạn không gọi generate(), thì testAction () sẽ làm điều đó nội bộ cho bạn với các giá trị mặc định của CakePHP (mocking _stop() và hàm redirect()) –

+0

Tôi nghĩ 'generate()' thực sự đã làm một cái gì đó khác. Đó là lý do tại sao tôi cứ nghĩ tại sao lại sử dụng nó nếu 'ControllerTestCase' cung cấp cho tôi một cấu hình mặc định. Tôi sẽ thử câu trả lời của bạn và cho bạn biết :) – elitalon

0

Thay vì:

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

Hãy thử một trong những:

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

Nó cũng không hoạt động. Những phương pháp này có phải là tương đương không? – elitalon

0

Set nó như vậy:

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

Đánh Câu chuyện mang lại cho tôi những answer in a CakePHP ticket. Về cơ bản tôi phải đăng nhập người dùng như thế này:

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

thay vì

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

Tôi thích Jose's answer, nhưng khi phải đối mặt với một tình huống tương tự tôi muốn sử dụng AuthComponent thực tế và phiên để tạo ra một bài kiểm tra đó sẽ cho tôi sự tự tin.

Tôi đang sử dụng xác thực dựa trên bộ điều khiển, có nghĩa là mỗi bộ điều khiển trong ứng dụng của tôi phải cung cấp gọi lại isAuthorized() riêng. Tôi muốn kiểm tra MyController :: isAuthorized(). Có vẻ như quá dễ dàng để có được một bài kiểm tra để vượt qua bằng cách sử dụng mocks.Vì vậy, thay vì sử dụng TestCase :: generate() để tạo ra một bộ điều khiển giả lập với các thành phần giả, tôi đã theo dõi bài viết xuất sắc của Mark Story Testing CakePHP Controllers the hard way và cung cấp bộ điều khiển giả của riêng tôi đăng nhập vào một người dùng với phần mềm CakePHP AuthComponent thực sự.

Đây là my work. Xem phương thức testIsAuthorized() và lớp def cho MockAnnouncementsController ở gần đầu.

Dường như với tôi khung công tác kiểm tra CakePHP giả định rằng bạn chỉ muốn kiểm tra bộ điều khiển thông qua requestAction(). Nó không được thiết kế để tạo điều kiện cho việc kiểm thử đơn vị trực tiếp thực hiện gọi lại như Controller :: isAuthorized() trong bộ điều khiển mà không mô phỏng AuthComponent và có lẽ các thành phần khác, và điều đó sẽ cho tôi ít tự tin hơn trong việc kiểm tra phương thức cụ thể đó. Tuy nhiên, tôi nghĩ đây là trường hợp sử dụng hợp lệ đối với các bộ phận kiểm thử đơn vị của bộ điều khiển không phải là hành động (ví dụ "chỉ mục", "xem"), nhưng không thể được ủy quyền cho một thành phần vì chúng phải được khung lõi gọi . Tôi vẫn nghĩ về cách tôi có thể tóm tắt nó để làm cho nó có sẵn cho bất kỳ bộ điều khiển nào.

Các vấn đề liên quan