在最终让我的愚蠢简单测试通过之后,我感觉我没有正确地做到这一点.
我有一个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类中存在的调用方法.尝试查看this article关于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; } }