[Laravel5.2 documentation] service-test

Source: Internet
Author: User
[Laravel5.2 documentation] service-test 1. Introduction

Laravel is rooted in testing. In fact, built-in PHPUnit is used to provide out-of-the-box support for testing, and the phpunit. xml file has been set for the application. The framework also provides convenient auxiliary methods for you to perform expressive tests on your applications.

The tests directory provides an ExampleTest. php file. after installing the new Laravel application, you just need to run phpunit on the command line to run the test.

1.1 Test Environment

Laravel automatically sets the configuration environment to testing when running the test. Laravel automatically configures the session and cache drivers as array drivers during the test, which means that the session and cache will not be stored persistently during the test.

You can also create other test environment configurations if needed. Testing Environment variables can be configured in the phpunit. xml file.

1.2 define and run the test

To create a new test case, run the following Artisan command:

php artisan make:test UserTest

This command will generate a new UserTest class under the tests directory. Then you can use PHPUnit to define the test method. To run the test, simply run the phpunit command from the terminal:

 assertTrue(true);    }}

Note: If you define your own setUp method in the Test class, make sure to call parent: setUp.

2. Application Testing

Laravel provides a smooth API for generating HTTP requests, test output, and filling forms. For example, let's take a look at the ExampleTest. php file contained in the tests Directory:

 Visit ('/')-> see ('laravel 5')-> dontSee ('Rails ');}}

The visit method generates a GET request. the see method asserted the given text that we should see in the response from the application. The dontSee method does not assert that the given text is returned from the application response. In Laravel, this is the most basic effective application test.

2.1 Interaction with applications

Of course, in addition to assertions of the response text, there are also more tests. let's take a look at some examples of clicking links and filling forms:

Click link

In this test, we will generate a request for the application, click the link in the returned response, and then assert the access URI. For example, assume that there is a "About Us" link in the response:

About Us

Now, let's write a test click link and assert whether the user access page is correct:

public function testBasicExample(){    $this->visit('/')         ->click('About Us')         ->seePageIs('/about-us');}

Process form

Laravel also provides multiple methods for processing forms. The type, select, check, attach, and press methods allow you to interact with all form inputs. For example, assume that this form exists on the application registration page:

 

We can write the test completion form and check the result:

public function testNewUserRegistration(){    $this->visit('/register')         ->type('Taylor', 'name')         ->check('terms')         ->press('Register')         ->seePageIs('/dashboard');}

Of course, if your form contains other inputs, such as single-choice buttons or drop-down lists, you can easily enter these field types. Here is a list of all form operation methods:

Method Description
$ This-> type ($ text, $ elementName) "Type" text to the given field
$ This-> select ($ value, $ elementName) "Select" single region or drop-down list
$ This-> check ($ elementName) Check box
$ This-> attach ($ pathToFile, $ elementName) "Attach" file to form
$ This-> press ($ buttonTextOrElementName) Press button for text or name
$ This-> uncheck ($ elementName) "Uncheck" check box

Process attachments

If the form contains the file input type, you can use the attach method to add the file to the form:

public function testPhotoCanBeUploaded(){    $this->visit('/upload')         ->name('File Name', 'name')         ->attach($absolutePathToFile, 'photo')         ->press('Upload')         ->see('Upload Successful!');}
2.2 Test JSON API

Laravel also provides multiple help functions for testing JSON APIs and their responses. For example, the get, post, put, patch, and delete methods are used to send requests through multiple HTTP request methods. You can also easily pass data and headers to these methods. At the beginning, we wrote a test to generate a POST request to/user and asserted whether the returned data is in JSON format:

 Post ('/user', ['name' => 'Sally'])-> seeJson (['created '=> true,]);}

The seeJson method converts a given array to JSON, and then verifies the JSON fragments in the entire JSON response returned by the application. Therefore, if there are other attributes in the JSON response, the test will still pass as long as the given segment exists.

Verify JSON value matching

If you want to verify the exact match between the given array and the JSON returned by the application, use the seeJsonEquals method:

 Post ('/user', ['name' => 'Sally'])-> seeJsonEquals (['created '=> true,]);}

Verify JSON data structure matching

You can also verify whether the JSON response matches the specified data structure. We use the seeJsonStructure method to implement this function:

 get('/user/1')             ->seeJsonStructure([                 'name',                 'pet' => [                     'name', 'age'                 ]             ]);    }}

The preceding example shows how to obtain JSON data that contains the name and nested pet object (the object contains the name and age attributes. If the JSON response contains other additional keys, seeJsonStructure will not fail. for example, if the pet object contains the weight attribute, the test will still pass.

You can use * to assert that the returned JSON structure contains a list. each data item in the list contains at least the attributes listed in the following example:

 get('/users')             ->seeJsonStructure([                 '*' => [                     'id', 'name', 'email'                 ]             ]);    }}

You can also use nested *. In this scenario, we can assert that every user in the JSON response contains a given property set, and each pet of each user contains a given property set:

$this->get('/users')     ->seeJsonStructure([         '*' => [             'id', 'name', 'email', `pets` => [                 '*' => [                     'name', 'age'                 ]             ]         ]     ]);
2.3 Session/authentication

Laravel provides multiple helper functions to process sessions during testing. First, you can use the withSession method to set the Session value to a given array. This is useful when obtaining session data before the test request:

 withSession(['foo' => 'bar'])             ->visit('/');    }}

Of course, sessions are usually used to operate user statuses, such as authenticated users. The auxiliary function actingAs provides a simple method to authenticate a given user as the current user. for example, we use the model factory to generate and authenticate the user:

 create();        $this->actingAs($user)             ->withSession(['foo' => 'bar'])             ->visit('/')             ->see('Hello, '.$user->name);    }}

You can also specify which guard is used to authenticate a given user by passing the guard name as the second parameter of the actingAs function:

$this->actingAs($user, 'backend')
2.4 disable middleware

It is convenient to disable middleware for some tests during application testing. This mechanism allows you to isolate the routing and controller from the middleware for testing. Laravel contains a simple WithoutMiddlewaretrait, which can be used to automatically disable all middleware in the Test class:

     

If you only want to disable middleware in some methods, you can call the withoutMiddleware method in the test method:

  WithoutMiddleware (); $ this-> visit ('/')-> see ('laravel 5 ');}}
2.5 Custom HTTP requests

If you want to generate a custom HTTP request in the application and obtain the complete Illuminate \ Http \ Response object, you can use the call method:

public function testApplication(){    $response = $this->call('GET', '/');    $this->assertEquals(200, $response->status());}

If you want to generate a POST, PUT, or PATCH Request, you can input an array of input data in the Request. in the routing or controller, you can access the Request data through the Request instance:

$response = $this->call('POST', '/user', ['name' => 'Taylor']);
2.6 PHPUnit asserted method

Laravel provides additional assertions for PHPUnit testing:

Method Description
-> AssertResponseOk (); Whether or not the client response status code is 200
-> AssertResponseStatus ($ code ); Whether the client response status code is given $ code
-> AssertViewHas ($ key, $ value = null ); Whether the assertion response View contains a specified bound data segment
-> AssertViewHasAll (array $ bindings ); Whether the assertion view contains a list of bound data
-> AssertViewMissing ($ key ); Data Segment bound to the assertion response View is missing
-> AssertRedirectedTo ($ uri, $ with = []); Whether the client is redirected to a specified URI
-> AssertRedirectedToRoute ($ name, $ parameters = [], $ with = []); Whether the client is redirected to the specified route
-> AssertRedirectedToAction ($ name, $ parameters = [], $ with = []); Whether the client is redirected to a given action
-> AssertSessionHas ($ key, $ value = null ); Whether the assertion session contains a given value
-> AssertSessionHasAll (array $ bindings ); Assertion whether the session protects the eye value list
-> AssertSessionHasErrors ($ bindings = [], $ format = null ); Whether the assertion session contains an error binding
-> AssertHasOldInput (); Assertion sessio contains the last input data
3. process the database

Laravel also provides a variety of useful tools to make it easier to test database-driven applications. First, you can use the help function seeInDatabase to determine whether the data in the database matches the given data set. For example, if you want to go to the data table users to query whether the record exists through the condition where the email value is sally@example.com, we can do this:

Public function testDatabase () {// call the application... $ this-> seeInDatabase ('users', ['email '=> 'Sally @ foo.com']);}

Of course, the seeInDatabase method and other auxiliary methods are encapsulated for convenience. you can also use other built-in asserted methods of PHPUnit for testing.

3.1 reset the database after each test

It is usually useful to reset the database after each test, so that the data in the last Test will not affect the next Test.

Use migration

One way is to roll back the database after each test and re-migrate it before the next Test. Laravel provides a simple DatabaseMigrationstrait to automatically process the data for you. In the Test class, the trait is simply used as follows:

  Visit ('/')-> see ('laravel 5 ');}}

Use transactions

Another way is to wrap each test case into a database transaction. Laravel provides a convenient DatabaseTransactionstrait to automatically handle it for you:

  Visit ('/')-> see ('laravel 5 ');}}

Note: This trait only encapsulates default database connections in transactions.

3.2 Model factory

During testing, new data is usually inserted into the database before the test is executed. When creating test data, Laravel allows you to use "factories" to define a default set of attribute values for each Eloquent model without manually specifying values for each column. At the beginning, let's take a look at the database/factories/ModelFactory. php file, which contains a factory definition:

$factory->define(App\User::class, function (Faker\Generator $faker) {    return [        'name' => $faker->name,        'email' => $faker->email,        'password' => bcrypt(str_random(10)),        'remember_token' => str_random(10),    ];});

In the closure, as the factory definition, we return the default test values for all attributes in the model. This closure receives the Faker instance of the PHP library, allowing you to easily generate multiple types of random data for the test.

Of course, you can add more factories to the ModelFactory. php file.

Multiple factory types

Sometimes you may want to generate multiple factories for the same Eloquent model class. for example, apart from being used outdoors, you may want to generate a factory for the "administrator" user, you can use the defineAs method to define these factories:

$factory->defineAs(App\User::class, 'admin', function ($faker) {    return [        'name' => $faker->name,        'email' => $faker->email,        'password' => str_random(10),        'remember_token' => str_random(10),        'admin' => true,    ];});

You can use the raw method to obtain basic attributes without repeating all the attributes in the basic user factory. after obtaining these attributes, you only need to add the additional values you require:

$factory->defineAs(App\User::class, 'admin', function ($faker) use ($factory) {    $user = $factory->raw(App\User::class);    return array_merge($user, ['admin' => true]);});

Use factory in testing

After the factory is defined, you can use the global factory method in the test or database fill file to generate model instances. Therefore, let's take a look at some examples of model generation. first, we use the make method to create a model without saving it to the database:

Public function testDatabase () {$ user = factory (App \ User: class)-> make (); // user model test ...}

If you want to override some default values of the model, you can pass the array value to the make method. Only the specified value is replaced, and other data remains unchanged:

$user = factory(App\User::class)->make([    'name' => 'Abigail',]);

You can also create multiple model sets or create a set of the given type:

// Create 3 App \ User instances... $ users = factory (App \ User: class, 3)-> make (); // create an App \ User "admin" instance... $ user = factory (App \ User: class, 'admin')-> make (); // create 3 App \ User "admin" instances... $ users = factory (App \ User: class, 'admin', 3)-> make ();

Persistent factory model

The create method not only creates model instances, but also saves them to the database using the save method of Eloquent:

Public function testDatabase () {$ user = factory (App \ User: class)-> create (); // user model test ...}

You can still overwrite the attributes of the model by passing an array to the create method:

$user = factory(App\User::class)->create([    'name' => 'Abigail',]);

Add Association relation model

You can even persist multiple models to the database. In this example, we add a model associated with the created model. when multiple models are created using the create method, an Eloquent collection instance is returned, this allows you to use all the convenient methods provided by the collection, such as each:

$users = factory(App\User::class, 3)           ->create()           ->each(function($u) {                $u->posts()->save(factory(App\Post::class)->make());            });
4. simulation4.1 simulate an event

If you are using Laravel's time system heavily, you may want to simulate specific events during testing. For example, if you register a test user, you may not want all the time processors of UserRegistered to be triggered, because this may send a welcome email, and so on.

Laravel provides a convenient expectsEvents method to verify that the expected event is triggered, but it also prevents other processors from running the event:

  ExpectsEvents (App \ Events \ UserRegistered: class); // test the user registration code ...}}

You can use the doesntExpectEvents method to verify that a given event is not triggered:

  expectsEvents(App\Events\PodcastWasPurchased::class);        $this->doesntExpectEvents(App\Events\PaymentWasDeclined::class);        // Test purchasing podcast...    }}

If you want to prevent all events from running, you can use the withoutEvents method:

  WithoutEvents (); // test the user registration code ...}}
4.2 simulate a queue task

Sometimes, you may want to simply test the specified task distributed by the controller during the request, which allows you to isolate the test route/controller-to separate it from the task logic. of course, next, you can test the task itself in an independent test class.

Laravel provides a convenient expectsJobs method to verify that the expected task is distributed, but the task itself is not tested:

  ExpectsJobs (App \ Jobs \ PurchasePodcast: class); // Test and purchase the podcast code ...}}

Note: This method only checks the tasks that are distributed through the DispatchesJobstrait distribution method, and does not check the tasks that are directly distributed through Queue: push.

4.3 simulate a facade

During the test, you may often want to simulate the calling of the Laravel facade, for example, look at the following controller actions:

      

We can use the shouldReceive method to simulate the call of the Cache facade. this method returns a Mockery simulated instance. because the facade is parsed and managed through the Laravel service container, they are more testable than common static classes. For example, we can simulate the call of the Cache facade:

   once()                    ->with('key')                    ->andReturn('value');        $this->visit('/users')->see('value');    }}

Note: do not simulate the Request facade. Instead, pass the input to HTTP help functions such as call and post during the test.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.