После того, как я наконец пропустил свой глупый простой тест, у меня появилось ощущение, что я делаю это неправильно.
У меня есть 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, лучше.