Laravel HTTP测试请求伪造详解
在Laravel中,HTTP测试请求伪造主要涉及如何模拟不同的HTTP请求方法和请求数据,以下是详细的实现方法:

基础请求方法伪造
<?php
namespace Tests\Feature;
use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;
class HttpRequestTest extends TestCase
{
use RefreshDatabase;
/** @test */
public function test_basic_http_requests()
{
// GET请求
$response = $this->get('/api/users');
// POST请求
$response = $this->post('/api/users', [
'name' => 'John Doe',
'email' => 'john@example.com'
]);
// PUT请求
$response = $this->put('/api/users/1', [
'name' => 'Jane Doe'
]);
// PATCH请求
$response = $this->patch('/api/users/1', [
'email' => 'jane@example.com'
]);
// DELETE请求
$response = $this->delete('/api/users/1');
// 断言状态码
$response->assertStatus(200);
}
}
高级请求伪造
<?php
namespace Tests\Feature;
use Tests\TestCase;
class AdvancedHttpRequestTest extends TestCase
{
/** @test */
public function test_advanced_request_methods()
{
// 带JSON头部的请求
$response = $this->withHeaders([
'accept' => 'application/json',
'X-CSRF-TOKEN' => csrf_token(),
])->post('/api/login', [
'email' => 'user@example.com',
'password' => 'secret'
]);
// 伪造Ajax请求
$response = $this->call(
'POST',
'/api/data',
[],
[],
[],
['HTTP_X-Requested-With' => 'XMLHttpRequest']
);
// 带会话的请求
$response = $this->withSession([
'user_id' => 1,
'role' => 'admin'
])->get('/admin/dashboard');
// 带查询参数的GET请求
$response = $this->get('/api/search', [
'q' => 'laravel',
'per_page' => 20
]);
}
/** @test */
public function test_request_with_files()
{
// 文件上传请求
$response = $this->post('/api/upload', [
'file' => UploadedFile::fake()->image('avatar.jpg', 200, 200)
]);
// 多个文件上传
$response = $this->post('/api/multiple-upload', [
'files' => [
UploadedFile::fake()->image('image1.jpg'),
UploadedFile::fake()->image('image2.jpg')
]
]);
}
}
路由固定的请求伪造
<?php
namespace Tests\Feature;
use Tests\TestCase;
class RouteSpecificTest extends TestCase
{
/** @test */
public function test_route_specific_requests()
{
// 使用路由名称生成请求URL
$response = $this->post(route('users.store'), [
'name' => 'John',
'email' => 'john@example.com'
]);
// 带路由参数的请求
$response = $this->withMiddleware('auth')
->get(route('users.show', ['id' => 1]));
// 带空间参数的POST请求
$response = $this->post(route('users.update', ['user' => 1]), [
'name' => 'Updated Name'
]);
// JSON API请求
$response = $this->postJson('/api/v1/users', [
'name' => 'Jane',
'email' => 'jane@example.com'
]);
}
}
模拟认证用户
<?php
namespace Tests\Feature;
use Tests\TestCase;
use App\Models\User;
use Laravel\Sanctum\Sanctum;
class AuthenticatedRequestTest extends TestCase
{
/** @test */
public function test_authenticated_requests()
{
$user = User::factory()->create();
// 使用actingAs助手方法
$response = $this->actingAs($user)
->get('/dashboard');
// 指定守卫
$response = $this->actingAs($user, 'admin')
->get('/admin/dashboard');
// Sanctum API认证
Sanctum::actingAs($user, ['view-api']);
$response = $this->getJson('/api/users');
// 带Bearer Token的请求
$token = $user->createToken('api-token')->plainTextToken;
$response = $this->withToken($token)
->getJson('/api/user');
}
}
模拟请求头和IP地址
<?php
namespace Tests\Feature;
use Tests\TestCase;
class HeaderIpTest extends TestCase
{
/** @test */
public function test_custom_headers_and_ip()
{
// 自定义头部
$response = $this->withHeaders([
'Authorization' => 'Bearer token123',
'X-API-Key' => 'abcdef123456',
'User-Agent' => 'CustomAgent/1.0'
])->get('/api/data');
// 模拟IP地址
$response = $this->call(
'GET',
'/api/geo',
[],
[],
[],
[
'REMOTE_ADDR' => '192.168.1.100',
'HTTP_X_FORWARDED_FOR' => '203.0.113.1'
]
);
// 使用withServerVariables
$response = $this->withServerVariables([
'REMOTE_ADDR' => '10.0.0.1',
'HTTP_USER_AGENT' => 'TestBrowser/1.0'
])->post('/api/submit');
}
}
复杂业务场景测试
<?php
namespace Tests\Feature;
use Tests\TestCase;
use App\Models\Order;
use App\Models\User;
use Illuminate\Foundation\Testing\WithFaker;
class ComplexScenarioTest extends TestCase
{
use WithFaker;
/** @test */
public function test_typical_api_workflow()
{
// 创建数据
$user = User::factory()->create();
$order = Order::factory()->create(['user_id' => $user->id]);
// 1. 登录获取Token
$loginResponse = $this->postJson('/api/login', [
'email' => $user->email,
'password' => 'password123'
]);
$token = $loginResponse->json('data.token');
// 2. 使用Token请求数据
$orderResponse = $this->withHeaders([
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json'
])->getJson("/api/orders/{$order->id}");
$orderResponse->assertOk()
->assertJsonStructure([
'data' => [
'id',
'total',
'status'
]
]);
// 3. 提交复杂请求数据
$createResponse = $this->postJson('/api/orders', [
'customer_name' => $this->faker->name(),
'items' => [
['product_id' => 1, 'quantity' => 2],
['product_id' => 2, 'quantity' => 1]
],
'shipping_address' => [
'street' => $this->faker->streetAddress(),
'city' => $this->faker->city(),
'zip' => $this->faker->postcode()
]
]);
$createResponse->assertStatus(201);
}
}
测试JSON和XML请求
<?php
namespace Tests\Feature;
use Tests\TestCase;
class JsonXmlTest extends TestCase
{
/** @test */
public function test_json_and_xml_requests()
{
// JSON请求
$jsonResponse = $this->postJson('/api/users', [
'name' => 'John',
'email' => 'john@example.com'
]);
$jsonResponse->assertJson([
'success' => true
]);
// XML请求(需要自定义)
$xmlResponse = $this->call(
'POST',
'/api/xml-handler',
[],
[],
[],
['CONTENT_TYPE' => 'application/xml'],
'<root><name>John</name></root>'
);
// 断言JSON结构
$this->postJson('/api/users')
->assertJsonStructure([
'data' => [
'*' => [
'id',
'name',
'email'
]
]
]);
// 断言部分JSON
$this->getJson('/api/users/1')
->assertJsonFragment([
'name' => 'John Doe'
]);
}
}
请求伪造的最佳实践
<?php
namespace Tests\Feature;
use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;
class BestPracticesTest extends TestCase
{
use RefreshDatabase;
/**
* 使用辅助方法封装请求
*/
private function authenticateAndGetUser()
{
$user = \App\Models\User::factory()->create([
'email' => 'test@example.com',
'password' => bcrypt('password')
]);
$token = $user->createToken('test')->plainTextToken;
return [$user, $token];
}
/** @test */
public function test_best_practices()
{
// 1. 为测试创建数据工厂
$user = \App\Models\User::factory()->create();
$order = \App\Models\Order::factory()
->for($user)
->create();
// 2. 定义明确的测试意图
$this->withoutExceptionHandling(); // 调试时使用
// 3. 使用数据库事务
$response = $this->transact(function () {
return $this->post('/api/users', [
'name' => 'John',
'email' => 'john@example.com'
]);
});
// 4. 建立测试环境配置
$this->app['config']->set('api-timeout', 30);
// 5. 使用数据提供者进行多场景测试
$responses = collect([
['name' => 'John', 'email' => 'john@example.com'],
['name' => 'Jane', 'email' => 'jane@example.com']
])->map(function ($data) {
return $this->post('/api/users', $data);
});
$responses->each(function ($response) {
$response->assertStatus(201);
});
}
}
总结关键点:
- get()/post()/put()/patch()/delete() 是基本的请求方法
- postJson()/getJson() 用于JSON API请求
- actingAs() 模拟认证用户
- withHeaders() 设置请求头部
- withSession() 模拟会话数据
- call() 提供更底层的请求控制
- UploadedFile::fake() 模拟文件上传
- Sanctum::actingAs() 用于API认证测试
这些方法组合使用可以覆盖绝大多数HTTP测试场景。