![](/img/trans.png)
[英]Laravel 4.1 - Testing an Artisan command with Phpunit and Mockery
[英]Laravel testing with PHPUnit and Mockery - Setting up dependencies on Controller test
在最終讓我的愚蠢簡單測試通過后,我感覺我沒有正確地做到這一點。
我有一個SessionsController,負責顯示登錄頁面並記錄用戶。
我決定不使用外牆,這樣我就不必延長Laravel的TestCase並在我的單元測試中受到性能影響。 因此,我已通過控制器注入所有依賴項,如此 -
SessionsController - 構造函數
public function __construct(UserRepositoryInterface $user,
AuthManager $auth,
Redirector $redirect,
Environment $view )
{
$this->user = $user;
$this->auth = $auth;
$this->redirect = $redirect;
$this->view = $view;
}
我已經完成了必要的變量聲明和使用命名空間,我不打算將其包括在內,因為它是不必要的。
create方法檢測用戶是否被授權,如果是,則將其重定向到主頁,否則顯示登錄表單。
SessionsController - 創建
public function create()
{
if ($this->auth->user()) return $this->redirect->to('/');
return $this->view->make('sessions.login');
}
現在進行測試,我是新手,所以請耐心等待。
SessionsControllerTest
class SessionsControllerTest extends PHPUnit_Framework_TestCase {
public function tearDown()
{
Mockery::close();
}
public function test_logged_in_user_cannot_see_login_page()
{
# Arrange (Create mocked versions of dependencies)
$user = Mockery::mock('Glenn\Repositories\User\UserRepositoryInterface');
$authorizedUser = Mockery::mock('Illuminate\Auth\AuthManager');
$authorizedUser->shouldReceive('user')->once()->andReturn(true);
$redirect = Mockery::mock('Illuminate\Routing\Redirector');
$redirect->shouldReceive('to')->once()->andReturn('redirected to home');
$view = Mockery::mock('Illuminate\View\Environment');
# Act (Attempt to go to login page)
$session = new SessionsController($user, $authorizedUser, $redirect, $view);
$result = $session->create();
# Assert (Return to home page)
}
}
這一切都通過了,但我不想為我在SessionsControllerTest中編寫的每個測試聲明所有這些模擬的依賴項。 有沒有辦法在構造函數中聲明這些模擬的依賴項? 然后通過變量調用它們進行模擬?
您可以使用setUp
方法聲明整個測試類的全局依賴項。 它與您當前使用的tearDown
方法類似:
public function setUp()
{
// This method will automatically be called prior to any of your test cases
parent::setUp();
$this->userMock = Mockery::mock('Glenn\Repositories\User\UserRepositoryInterface');
}
但是,如果您的模擬設置在測試之間有所不同,那么這將不起作用。 對於這種情況,您可以使用輔助方法:
protected function getAuthMock($isLoggedIn = false)
{
$authorizedUser = Mockery::mock('Illuminate\Auth\AuthManager');
$authorizedUser->shouldReceive('user')->once()->andReturn($isLoggedIn);
}
然后當你需要auth mock時,你可以調用getAuthMock
。 這可以大大簡化您的測試。
然而
我認為你沒有正確測試你的控制器。 您不應該自己實例化控制器對象,而應該使用Laravel的TestCase
類中存在的call
方法。 嘗試查看關於Jeffrey Way測試Laravel控制器的這篇文章 。 我認為你希望在你的測試中做更多的事情:
class SessionsControllerTest extends TestCase
{
public function setUp()
{
parent::setUp();
}
public function tearDown()
{
Mockery::close();
}
public function test_logged_in_user_cannot_see_login_page()
{
// This will bind any instances of the Auth manager during
// the next request to the mock object returned from the
// function below
App::instance('Illuminate\Auth\Manager', $this->getAuthMock(true));
// Act
$this->call('/your/route/to/controller/method', 'GET');
// Assert
$this->assertRedirectedTo('/');
}
protected function getAuthMock($isLoggedIn)
{
$authMock = Mockery::mock('Illuminate\Auth\Manager');
$authMock->shouldReceive('user')->once()->andReturn($isLoggedIn);
return $authMock;
}
}
是的,你可以使用“助手”。 將模擬依賴項的創建移動到另一個函數中,然后在需要時調用它。 查看此演示文稿中的幻燈片52: https : //speakerdeck.com/jcarouth/guiding-object-oriented-design-with-tests-1 (查看整個內容,但示例在幻燈片52上)
編輯:setUp方式甚至更好,我正在考慮你在所有測試中不需要的東西,但我認為你所描述的在setUp中做的更好。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.