Laravel控制器的单元测试 [英] Laravel unit testing of controllers

查看:85
本文介绍了Laravel控制器的单元测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在TDD之后启动一个新的Laravel应用

我的第一步是检查/login控制器是否在主URL上被调用.

尽管遵循了一些教程,但我无法进行测试,也根本看不到自己在做什么错.

我的设置是: 作曲家安装laravel 作曲家安装phpunit

这是我的路线:

<?php
Route::get('/login', 'AuthenticationController@login');

我的控制器:

<?php

class AuthenticationController extends BaseController {

    public function login () {
        return View::make('authentication.login');
    }

}

我的测试:

<?php

class AuthenticationTest extends TestCase {

    public function testSomeTest () {

        $response = $this->action('GET', 'AuthenticationController@login');

        $view = $response->original;

        $this->assertEquals('authentication.login', $view['name']);
    }
}

我得到的错误是

  ErrorException: Undefined index: name

该代码是Laravel网站的副本(几乎完全是这样),但并未运行.

任何人都可以看到我在做什么吗?

它声称$ view没有索引名,但是不能正确使用它在laravel网站上的示例,另外,该视图使用其名称进行渲染(它也可以正确显示在前端)

:

因此,从一条评论看来,laravel单元测试部分尚不清楚,并且$ view ['name']正在检查名为$ name的变量.如果是这样,您如何测试所用的控制器/路由,即IE.路由('X')使用了什么控制器名称/动作名称

解决方案

好,正如评论中已经解释过的那样,让我们​​先退后一步来考虑一下这种情况.

我的第一步是检查/login控制器是否在主URL上被调用."

这意味着:当用户点击本地路由时,您要检查用户是否已登录.如果未登录,则希望将其重定向到登录名,也许会带有一些提示信息.他们登录后,您想将他们重定向回首页.如果登录失败,则希望将其重定向回登录表单,也可能会显示一条简短消息.

因此,现在有几项要测试:家庭控制器和登录控制器.因此,遵循TDD精神,让我们首先创建测试.

注意:我将遵循 phpspec 所使用的一些命名约定,但不要让这麻烦您

class HomeControllerTest extends TestCase
{
    /**
     * @test
     */
    public function it_redirects_to_login_if_user_is_not_authenticated()
    {
        Auth::shouldReceive('check')->once()->andReturn(false);

        $response = $this->call('GET', 'home');

        // Now we have several ways to go about this, choose the
        // one you're most comfortable with.

        // Check that you're redirecting to a specific controller action 
        // with a flash message
        $this->assertRedirectedToAction(
             'AuthenticationController@login', 
             null, 
             ['flash_message']
        );

        // Only check that you're redirecting to a specific URI
        $this->assertRedirectedTo('login');

        // Just check that you don't get a 200 OK response.
        $this->assertFalse($response->isOk());

        // Make sure you've been redirected.
        $this->assertTrue($response->isRedirection());
    }

    /**
     * @test
     */
    public function it_returns_home_page_if_user_is_authenticated()
    {
        Auth::shouldReceive('check')->once()->andReturn(true);

        $this->call('GET', 'home');

        $this->assertResponseOk();
    }
}

这就是Home控制器.在大多数情况下,您实际上并不在乎将您重定向到何处,因为随着时间的推移,这种情况可能会发生变化,因此您必须更改测试.因此,您至少应该做的就是检查您是否被重定向,并且仅在您真的认为对测试很重要的情况下才检查更多详细信息.

让我们看一下Authentication控制器:

class AuthenticationControllerTest extends TestCase
{
    /**
     * @test
     */
    public function it_shows_the_login_form()
    {
        $response = $this->call('GET', 'login');

        $this->assertTrue($response->isOk());

        // Even though the two lines above may be enough,
        // you could also check for something like this:

        View::shouldReceive('make')->with('login');
    }

    /**
     * @test
     */
    public function it_redirects_back_to_form_if_login_fails()
    {
        $credentials = [
            'email' => 'test@test.com',
            'password' => 'secret',
        ];

        Auth::shouldReceive('attempt')
             ->once()
             ->with($credentials)
             ->andReturn(false);

        $this->call('POST', 'login', $credentials);

        $this->assertRedirectedToAction(
            'AuthenticationController@login', 
            null, 
            ['flash_message']
        );
    }

    /**
     * @test
     */
    public function it_redirects_to_home_page_after_user_logs_in()
    {
        $credentials = [
            'email' => 'test@test.com',
            'password' => 'secret',
        ];

        Auth::shouldReceive('attempt')
             ->once()
             ->with($credentials)
             ->andReturn(true);

        $this->call('POST', 'login', $credentials);

        $this->assertRedirectedTo('home');
    }
}

再次,请始终考虑您真正想要测试的内容.您是否真的需要知道在哪个路由上触发了哪个控制器动作?或返回的视图名称是什么?实际上,您只需要确保控制器实际尝试即可执行此操作.您向它传递了一些数据,然后测试它的行为是否符合预期.

并始终确保您不尝试测试任何框架功能,例如,如果特定路由触发了特定操作或视图是否正确加载.这已经过测试,因此您不必担心.专注于应用程序的功能,而不关注底层框架.

I am trying to start a new Laravel app following TDD

My first step is to check that the /login controller is called on the home url.

Despite following several tutorials I can't get the test to work and I can't see what I'm doing wrong at all.

My set up is: composer to install laravel composer to install phpunit

here is my route:

<?php
Route::get('/login', 'AuthenticationController@login');

my controller:

<?php

class AuthenticationController extends BaseController {

    public function login () {
        return View::make('authentication.login');
    }

}

And my test:

<?php

class AuthenticationTest extends TestCase {

    public function testSomeTest () {

        $response = $this->action('GET', 'AuthenticationController@login');

        $view = $response->original;

        $this->assertEquals('authentication.login', $view['name']);
    }
}

The error I get is

  ErrorException: Undefined index: name

The code as a copy (pretty much exactly) from the Laravel site, yet it doesn't run.

Can anyone see what I'm doing wrong?

It claims $view has no index name, but that can't be right as its the example on the laravel website, plus the view is being rendered using its name (it is showing correctly on the front end too)

EDIT::

So it seems from a comment that the laravel unit testing section isn't clear and that the $view['name'] is checking for a variable called $name. If that is the case, how do you test the controller/route used, IE. what controller name/action name has been used for route('X')

解决方案

Ok, as already explained a little in the comments, let's first take a step back and think about the scenario.

"My first step is to check that the /login controller is called on the home url."

So that means: When the user hits the home route, you want to check if the user is logged in. If he's not, you want to redirect them to the login, maybe with some flash message. After they have logged in, you want to redirect them back to the home page. If the login fails, you want to redirect them back to the login form, maybe also with a flash message.

So there are several things to test now: The home controller and the login controller. So following the TDD spirit, let's create the tests first.

Note: I'll follow some naming convention that is used by phpspec, but don't let that bother you.

class HomeControllerTest extends TestCase
{
    /**
     * @test
     */
    public function it_redirects_to_login_if_user_is_not_authenticated()
    {
        Auth::shouldReceive('check')->once()->andReturn(false);

        $response = $this->call('GET', 'home');

        // Now we have several ways to go about this, choose the
        // one you're most comfortable with.

        // Check that you're redirecting to a specific controller action 
        // with a flash message
        $this->assertRedirectedToAction(
             'AuthenticationController@login', 
             null, 
             ['flash_message']
        );

        // Only check that you're redirecting to a specific URI
        $this->assertRedirectedTo('login');

        // Just check that you don't get a 200 OK response.
        $this->assertFalse($response->isOk());

        // Make sure you've been redirected.
        $this->assertTrue($response->isRedirection());
    }

    /**
     * @test
     */
    public function it_returns_home_page_if_user_is_authenticated()
    {
        Auth::shouldReceive('check')->once()->andReturn(true);

        $this->call('GET', 'home');

        $this->assertResponseOk();
    }
}

And that's it for the Home controller. In most cases you actually don't care where you are redirected to, because that may change over time and you would have to change the tests. So the least you should do is to check whether you are being redirected or not and only check for more details if you really think that it matters for your test.

Let's have a look at the Authentication controller:

class AuthenticationControllerTest extends TestCase
{
    /**
     * @test
     */
    public function it_shows_the_login_form()
    {
        $response = $this->call('GET', 'login');

        $this->assertTrue($response->isOk());

        // Even though the two lines above may be enough,
        // you could also check for something like this:

        View::shouldReceive('make')->with('login');
    }

    /**
     * @test
     */
    public function it_redirects_back_to_form_if_login_fails()
    {
        $credentials = [
            'email' => 'test@test.com',
            'password' => 'secret',
        ];

        Auth::shouldReceive('attempt')
             ->once()
             ->with($credentials)
             ->andReturn(false);

        $this->call('POST', 'login', $credentials);

        $this->assertRedirectedToAction(
            'AuthenticationController@login', 
            null, 
            ['flash_message']
        );
    }

    /**
     * @test
     */
    public function it_redirects_to_home_page_after_user_logs_in()
    {
        $credentials = [
            'email' => 'test@test.com',
            'password' => 'secret',
        ];

        Auth::shouldReceive('attempt')
             ->once()
             ->with($credentials)
             ->andReturn(true);

        $this->call('POST', 'login', $credentials);

        $this->assertRedirectedTo('home');
    }
}

Again, always think about what you really want to test. Do you really need to know which controller action is triggered on which route? Or what the name of the view is that is returned? Actually, you just need to make sure that the controller actually attempts to do it. You pass it some data and then test if it behaves as expected.

And always make sure you're not trying to test any framework functionality, for instance if a specific route triggers a specific action or if a View is loaded correctly. This has already been tested, so you don't need to worry about that. Focus on the functionality of your application and not on the underlying framework.

这篇关于Laravel控制器的单元测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆