Тестирование Laravel с помощью PHPUnit и Mockery – Настройка зависимостей от теста Controller

После того, как я наконец пропустил свой глупый простой тест, у меня появилось ощущение, что я делаю это неправильно.

У меня есть SessionController, который отвечает за отображение страницы входа и регистрации пользователя.

Я решил не использовать фасады, так что мне не пришлось бы продлевать TestCase Laravel и делать удар производительности на моих модульных тестах. Поэтому я ввел все зависимости через контроллер, например,

SessionController – конструктор

public function __construct(UserRepositoryInterface $user, AuthManager $auth, Redirector $redirect, Environment $view ) { $this->user = $user; $this->auth = $auth; $this->redirect = $redirect; $this->view = $view; } 

Я сделал необходимое объявление переменных и использование пространств имен, которые я не собираюсь включать здесь в качестве ненужных.

метод create определяет, разрешен ли пользователь, если они затем переадресовывают их на домашнюю страницу, в противном случае они отображают форму входа.

SessionController – Создать

 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) } } 

Все это проходит, но я не хочу объявлять все эти издевательства зависимостей для каждого теста, который я пишу в своем SessionControllerTest. Есть ли способ объявить эти издеваемые зависимости один раз в конструкторе? а затем называть их переменными для насмешек?

Спасибо за любые предложения и не торопитесь, чтобы прочитать мой вопрос.

Вы можете использовать метод 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); } 

Затем, когда вам нужен getAuthMock вы можете просто вызвать getAuthMock . Это может значительно упростить ваши тесты.

Однако

Я не думаю, что вы правильно тестируете ваш контроллер. Вы не должны создавать экземпляр объекта контроллера самостоятельно, вместо этого вы должны использовать метод call который существует в классе TestCase Laravel. Попробуйте проверить эту статью о тестировании контроллеров 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)

Edit: метод setUp еще лучше, я думал о чем-то, что вам не нужно во ВСЕХ тестах, но я думаю, что то, что вы описали, делает это в setUp, лучше.