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()
ますtestDestroyOkRoute()
。prepDestroyOk()
両方のテスト ケースは、一貫性を確保するために共通の方法を使用してセットアップされます。
それでも、コントローラーのメソッドから ResourceNotFoundException をスローするため、成功して失敗しますtestDestroyOk()
。testDestroyOkRoute()
getUser()
コントローラーへのアクセスが機能するのに、ルートを経由するのがどういうわけか異なる方法で処理される理由はありますか?