编写 然后编写注册测试用例:编写 最后,编写退出测试用例:编辑 编写 要运行测试的话的随时运行
LoginTest
代码如下:1
class LoginTest extends TestCase
2
{
3
public function testRequiresEmailAndLogin()
4
{
5
$this->json('POST', 'api/login')
6
->assertStatus(422)
7
->assertJson([
8
'email' => ['The email field is required.'],
9
'password' => ['The password field is required.'],
10
]);
11
}
12
13
public function testUserLoginsSuccessfully()
14
{
15
$user = factory(User::class)->create([
16
'email' => 'test@laravelacademy.org',
17
'password' => bcrypt('test123'),
18
]);
19
20
$payload = ['email' => 'test@laravelacademy.org', 'password' => 'test123'];
21
22
$this->json('POST', 'api/login', $payload)
23
->assertStatus(200)
24
->assertJsonStructure([
25
'data' => [
26
'id',
27
'name',
28
'email',
29
'created_at',
30
'updated_at',
31
'api_token',
32
],
33
]);
34
35
}
36
}
1
php artisan make:test RegisterTest
RegisterTest
代码如下:1
class RegisterTest extends TestCase
2
{
3
public function testsRegistersSuccessfully()
4
{
5
$payload = [
6
'name' => 'John',
7
'email' => 'john@toptal.com',
8
'password' => 'toptal123',
9
'password_confirmation' => 'toptal123',
10
];
11
12
$this->json('post', '/api/register', $payload)
13
->assertStatus(201)
14
->assertJsonStructure([
15
'data' => [
16
'id',
17
'name',
18
'email',
19
'created_at',
20
'updated_at',
21
'api_token',
22
],
23
]);;
24
}
25
26
public function testsRequiresPasswordEmailAndName()
27
{
28
$this->json('post', '/api/register')
29
->assertStatus(422)
30
->assertJson([
31
'name' => ['The name field is required.'],
32
'email' => ['The email field is required.'],
33
'password' => ['The password field is required.'],
34
]);
35
}
36
37
public function testsRequirePasswordConfirmation()
38
{
39
$payload = [
40
'name' => 'John',
41
'email' => 'john@toptal.com',
42
'password' => 'toptal123',
43
];
44
45
$this->json('post', '/api/register', $payload)
46
->assertStatus(422)
47
->assertJson([
48
'password' => ['The password confirmation does not match.'],
49
]);
50
}
51
}
1
php artisan make:test LogoutTest
LogoutTest
代码如下:1
class LogoutTest extends TestCase
2
{
3
public function testUserIsLoggedOutProperly()
4
{
5
$user = factory(User::class)->create(['email' => 'user@test.com']);
6
$token = $user->generateToken();
7
$headers = ['Authorization' => "Bearer $token"];
8
9
$this->json('get', '/api/articles', [], $headers)->assertStatus(200);
10
$this->json('post', '/api/logout', [], $headers)->assertStatus(200);
11
12
$user = User::find($user->id);
13
14
$this->assertEquals(null, $user->api_token);
15
}
16
17
public function testUserWithNullToken()
18
{
19
// Simulating login
20
$user = factory(User::class)->create(['email' => 'user@test.com']);
21
$token = $user->generateToken();
22
$headers = ['Authorization' => "Bearer $token"];
23
24
// Simulating logout
25
$user->api_token = null;
26
$user->save();
27
28
$this->json('get', '/api/articles', [], $headers)->assertStatus(401);
29
}
30
}
注:在测试期间,Laravel 应用并不会在发起新请求时再次初始化,所以会在请求之间保存当前用户到 TokenGuard
实例,也因此我们不得不将退出测试一分为二,以避免受之前缓存用户的影响。
测试文章 API 接口的代码也很简单:1
php artisan make:test ArticleTest
ArticleTest
代码如下:1
class ArticleTest extends TestCase
2
{
3
public function testsArticlesAreCreatedCorrectly()
4
{
5
$user = factory(User::class)->create();
6
$token = $user->generateToken();
7
$headers = ['Authorization' => "Bearer $token"];
8
$payload = [
9
'title' => 'Lorem',
10
'body' => 'Ipsum',
11
];
12
13
$this->json('POST', '/api/articles', $payload, $headers)
14
->assertStatus(200)
15
->assertJson(['id' => 1, 'title' => 'Lorem', 'body' => 'Ipsum']);
16
}
17
18
public function testsArticlesAreUpdatedCorrectly()
19
{
20
$user = factory(User::class)->create();
21
$token = $user->generateToken();
22
$headers = ['Authorization' => "Bearer $token"];
23
$article = factory(Article::class)->create([
24
'title' => 'First Article',
25
'body' => 'First Body',
26
]);
27
28
$payload = [
29
'title' => 'Lorem',
30
'body' => 'Ipsum',
31
];
32
33
$response = $this->json('PUT', '/api/articles/' . $article->id, $payload, $headers)
34
->assertStatus(200)
35
->assertJson([
36
'id' => 1,
37
'title' => 'Lorem',
38
'body' => 'Ipsum'
39
]);
40
}
41
42
public function testsArtilcesAreDeletedCorrectly()
43
{
44
$user = factory(User::class)->create();
45
$token = $user->generateToken();
46
$headers = ['Authorization' => "Bearer $token"];
47
$article = factory(Article::class)->create([
48
'title' => 'First Article',
49
'body' => 'First Body',
50
]);
51
52
$this->json('DELETE', '/api/articles/' . $article->id, [], $headers)
53
->assertStatus(204);
54
}
55
56
public function testArticlesAreListedCorrectly()
57
{
58
factory(Article::class)->create([
59
'title' => 'First Article',
60
'body' => 'First Body'
61
]);
62
63
factory(Article::class)->create([
64
'title' => 'Second Article',
65
'body' => 'Second Body'
66
]);
67
68
$user = factory(User::class)->create();
69
$token = $user->generateToken();
70
$headers = ['Authorization' => "Bearer $token"];
71
72
$response = $this->json('GET', '/api/articles', [], $headers)
73
->assertStatus(200)
74
->assertJson([
75
[ 'title' => 'First Article', 'body' => 'First Body' ],
76
[ 'title' => 'Second Article', 'body' => 'Second Body' ]
77
])
78
->assertJsonStructure([
79
'*' => ['id', 'body', 'title', 'created_at', 'updated_at'],
80
]);
81
}
82
}
composer test
即可。 至此,我们已经完成了 API 接口的编写和测试,下一篇我们会基于 JWT 对 API 进行认证同时整合进 Vue SPA 做一个更偏向实战的教程,敬请期待。
87 条评论
为啥不用 PHPStorm 呢,会自动给你引进来
学院君我想问下我测试注册接口的时候返回的{ "message": "Type error: Argument 1 passed to App\Http\Controllers\Auth\RegisterController::registered() must be an instance of App\Http\Controllers\Auth\Request, instance of Illuminate\Http\Request given, called in D:\phpstudy\PHPTutorial\WWW\laravel\vendor\laravel\framework\src\Illuminate\Foundation\Auth\RegistersUsers.php on line 37", "exception": "Symfony\Component\Debug\Exception\FatalThrowableError", "file": ...这个错误,但是我数据库却写进去了是什么情况
@ 学院君 注册时users表生成的api_token值 和登录时返回的api_token值不一样是什么情况?
登陆操作以后 我换个控制器 获取用户信息 为什么获取不到
加了认证中间件以后 登陆之后 访问/articles 还是 { "message": "Unauthenticated." }
API 认证后获取到的 token 后续每次请求都要在请求参数中带上 这里采用 Authorization 请求头的方式传递 不同于传统的通过 Cookie+Session 实现的认证 这种情况下 SessionID 写入到 Cookie 中每次自动带上
Laravel6.0 没有
str_random()
函数了,取而代之的是Str::random()
方法