我正在使用 Laravel 4 和 Mockery 为控制器构建一些单元测试。
我一直在通过直接调用控制器方法(以单独对方法进行单元测试)和通过路由调用方法(以专注于响应)进行测试,但根据我是否调用控制器与走路线。
这是我足智多谋的控制器:
class UserController extends \BaseController {
protected $user;
public function __construct(User $user)
{
$this->user = $user;
}
/**
* Remove the specified resource from storage.
*
* @param int $id
*/
public function destroy($id)
{
// Get and delete user
$this->getUser($id);
$this->user->delete();
return $this->ok(); // This is just a json response::json
}
/**
* Attempts to find the user requested
*
* @param $id The ID they are trying to find
*/
private function getUser($id)
{
// Attempt to find the user
$this->user = $this->user->find($id);
// Throw exception if we can't find it
if(is_null($this->user)) throw new ResourceNotFoundException('User '.$id.' not found');
return;
}
这是我的路线:
Route::resource('users', 'UserController', array('only' => array('index', 'store','show','update','destroy')));
这是我的测试:
use Way\Tests\Factory;
class UserControllerUnitTest extends TestCase {
public function setUp()
{
parent::setUp();
// Fake objects
$this->fake_user_nonadmin = Factory::user(array('id' => 2, 'admin' => FALSE, 'deleted_at' => null));
// Mock objects
$this->mock_user = Mockery::mock('User')->makePartial();
// Make the controller
$this->controller = new UserController($this->mock_user);
}
public function tearDown()
{
Mockery::close();
}
protected function prepDestroyOk($id)
{
$this->mock_user
->shouldReceive('find')
->once()
->with($id)
->andReturn($this->mock_user);
$this->mock_user
->shouldReceive('delete')
->once()
->andReturn('foo');
}
public function testDestroyOk()
{
$id = $this->fake_user_nonadmin->id;
$this->prepDestroyOk($id);
$this->controller->destroy($id);
}
public function testDestroyOkRoute()
{
$id = $this->fake_user_nonadmin->id;
$this->prepDestroyOk($id);
$response = $this->client->request('DELETE', 'users/'.$id);
$this->assertResponseOk();
$this->assertEquals(get_class($response), "Illuminate\Http\JsonResponse");
}
你看我正在测试直接控制器访问testDestroyOk()
,而不是通过 routes.php 调用相同的方法testDestroyOkRoute()
。两个测试用例都是使用通用prepDestroyOk()
方法设置的,以确保它们是一致的。
然而,当它从我的控制器中的方法抛出 ResourceNotFoundException 时testDestroyOk()
通过并testDestroyOkRoute()
失败。getUser()
任何想法为什么访问控制器有效但通过路由以某种方式被不同地对待?