PHP 模拟请求测试接口

wen PHP项目 2

本文目录导读:

PHP 模拟请求测试接口

  1. 使用 cURL(最常用)
  2. 使用 file_get_contents(简单场景)
  3. 完整的请求封装类
  4. 使用 GuzzleHttp(Composer 包)
  5. 批量测试工具
  6. 命令行测试脚本
  7. 使用 PHPUnit 测试
  8. 最佳实践建议

在 PHP 中模拟请求测试接口有多种方法,我来介绍几种最常用的方案:

使用 cURL(最常用)

GET 请求

<?php
function sendGetRequest($url, $headers = []) {
    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => $headers,
        CURLOPT_TIMEOUT => 30,
        CURLOPT_SSL_VERIFYPEER => false // 跳过SSL验证
    ]);
    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $error = curl_error($ch);
    curl_close($ch);
    return [
        'status' => $httpCode,
        'body' => $response,
        'error' => $error
    ];
}
// 使用示例
$result = sendGetRequest('https://api.example.com/users', [
    'Authorization: Bearer your_token',
    'Content-Type: application/json'
]);
echo json_encode($result);

POST 请求

<?php
function sendPostRequest($url, $data, $headers = []) {
    $ch = curl_init();
    $defaultHeaders = [
        'Content-Type: application/json'
    ];
    $headers = array_merge($defaultHeaders, $headers);
    curl_setopt_array($ch, [
        CURLOPT_URL => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => json_encode($data),
        CURLOPT_HTTPHEADER => $headers,
        CURLOPT_TIMEOUT => 30
    ]);
    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    return [
        'status' => $httpCode,
        'body' => $response
    ];
}
// 使用示例
$result = sendPostRequest('https://api.example.com/users', [
    'name' => '张三',
    'email' => 'zhangsan@example.com'
]);

使用 file_get_contents(简单场景)

<?php
// GET 请求
$url = 'https://api.example.com/users?page=1';
$options = [
    'http' => [
        'method' => 'GET',
        'header' => "Authorization: Bearer token\r\n"
    ]
];
$context = stream_context_create($options);
$response = file_get_contents($url, false, $context);
// POST 请求
$data = ['name' => '李四', 'age' => 25];
$options = [
    'http' => [
        'method' => 'POST',
        'header' => "Content-Type: application/json\r\n",
        'content' => json_encode($data)
    ]
];
$context = stream_context_create($options);
$response = file_get_contents('https://api.example.com/users', false, $context);

完整的请求封装类

<?php
class ApiClient {
    private $baseUrl;
    private $headers;
    private $timeout;
    public function __construct($baseUrl = '', $timeout = 30) {
        $this->baseUrl = $baseUrl;
        $this->timeout = $timeout;
        $this->headers = [
            'Content-Type: application/json',
            'Accept: application/json'
        ];
    }
    // 设置请求头
    public function setHeader($header) {
        $this->headers[] = $header;
        return $this;
    }
    // GET 请求
    public function get($path, $params = []) {
        $url = $this->baseUrl . $path;
        if (!empty($params)) {
            $url .= '?' . http_build_query($params);
        }
        return $this->execute($url, 'GET');
    }
    // POST 请求
    public function post($path, $data = []) {
        $url = $this->baseUrl . $path;
        return $this->execute($url, 'POST', $data);
    }
    // PUT 请求
    public function put($path, $data = []) {
        $url = $this->baseUrl . $path;
        return $this->execute($url, 'PUT', $data);
    }
    // DELETE 请求
    public function delete($path) {
        $url = $this->baseUrl . $path;
        return $this->execute($url, 'DELETE');
    }
    // 执行请求
    private function execute($url, $method, $data = []) {
        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => $this->timeout,
            CURLOPT_CUSTOMREQUEST => $method,
            CURLOPT_HTTPHEADER => $this->headers,
            CURLOPT_SSL_VERIFYPEER => false
        ]);
        // POST 数据
        if (!empty($data)) {
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        }
        $response = curl_exec($ch);
        $error = curl_error($ch);
        $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        return (object) [
            'success' => $error ? false : true,
            'status' => $statusCode,
            'data' => $response ? json_decode($response, true) : null,
            'error' => $error,
            'raw' => $response
        ];
    }
}
// 使用示例
$client = new ApiClient('https://api.example.com');
$client->setHeader('Authorization: Bearer your_token');
// GET 请求
$result = $client->get('/users', ['page' => 1, 'size' => 10]);
// POST 请求
$result = $client->post('/users', [
    'name' => '王五',
    'email' => 'wangwu@example.com'
]);
if ($result->success) {
    echo "请求成功,状态码:" . $result->status;
    print_r($result->data);
} else {
    echo "请求失败:" . $result->error;
}

使用 GuzzleHttp(Composer 包)

安装

composer require guzzlehttp/guzzle

使用示例

<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Response;
$client = new Client([
    'base_uri' => 'https://api.example.com',
    'timeout' => 30,
    'verify' => false
]);
try {
    // GET 请求
    $response = $client->get('/users', [
        'query' => ['page' => 1, 'size' => 10],
        'headers' => [
            'Authorization' => 'Bearer token'
        ]
    ]);
    $body = $response->getBody();
    $data = json_decode($body, true);
    echo "状态码:" . $response->getStatusCode();
    print_r($data);
} catch (Exception $e) {
    echo "请求错误:" . $e->getMessage();
}
// POST 请求
$response = $client->post('/users', [
    'json' => [
        'name' => '赵六',
        'email' => 'zhaoliu@example.com'
    ],
    'headers' => [
        'Authorization' => 'Bearer token'
    ]
]);

批量测试工具

<?php
class ApiTester {
    private $tests = [];
    private $baseUrl;
    public function __construct($baseUrl) {
        $this->baseUrl = $baseUrl;
    }
    // 添加测试用例
    public function addTest($name, $method, $path, $data = [], $expectedStatus = 200) {
        $this->tests[] = compact('name', 'method', 'path', 'data', 'expectedStatus');
        return $this;
    }
    // 运行所有测试
    public function run() {
        $results = [];
        foreach ($this->tests as $test) {
            $start = microtime(true);
            // 发送请求
            $result = $this->sendRequest(
                $test['method'], 
                $test['path'], 
                $test['data']
            );
            $executionTime = microtime(true) - $start;
            $passed = $result['status'] == $test['expectedStatus'];
            $results[] = [
                'name' => $test['name'],
                'passed' => $passed,
                'status' => $result['status'],
                'expected' => $test['expectedStatus'],
                'time' => round($executionTime, 3) . 's',
                'response' => $result['body']
            ];
        }
        return $results;
    }
    // 发送请求
    private function sendRequest($method, $path, $data) {
        $url = $this->baseUrl . $path;
        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_CUSTOMREQUEST => $method,
            CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
            CURLOPT_SSL_VERIFYPEER => false
        ]);
        if (!empty($data)) {
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        }
        $body = curl_exec($ch);
        $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        return ['status' => $status, 'body' => $body];
    }
    // 打印测试报告
    public function printReport($results) {
        $passed = 0;
        $failed = 0;
        echo "========== API 测试报告 ==========\n\n";
        foreach ($results as $result) {
            $status = $result['passed'] ? '✅ PASS' : '❌ FAIL';
            echo "{$status} | {$result['name']}\n";
            echo "   状态码: {$result['status']} (期望: {$result['expected']})\n";
            echo "   耗时: {$result['time']}\n";
            if (!$result['passed']) {
                echo "   响应: {$result['response']}\n";
                $failed++;
            } else {
                $passed++;
            }
            echo "\n";
        }
        echo "========== 测试统计 ==========\n";
        echo "总测试数: " . count($results) . "\n";
        echo "通过: {$passed}\n";
        echo "失败: {$failed}\n";
        echo "成功率: " . round($passed / count($results) * 100, 2) . "%\n";
    }
}
// 使用示例
$tester = new ApiTester('http://localhost:8000/api');
// 添加测试用例
$tester->addTest('获取用户列表', 'GET', '/users')
       ->addTest('创建用户', 'POST', '/users', ['name' => '测试用户'], 201)
       ->addTest('获取单个用户', 'GET', '/users/1')
       ->addTest('更新用户', 'PUT', '/users/1', ['name' => '更新名称'])
       ->addTest('删除用户', 'DELETE', '/users/1', [], 204);
// 运行测试
$results = $tester->run();
$tester->printReport($results);

命令行测试脚本

#!/usr/bin/env php
<?php
// test_api.php
parse_str(implode('&', array_slice($argv, 1)), $args);
$method = $args['method'] ?? 'GET';
$url = $args['url'] ?? '';
$data = json_decode($args['data'] ?? '{}', true);
$token = $args['token'] ?? '';
$ch = curl_init();
$headers = ['Content-Type: application/json'];
if ($token) {
    $headers[] = "Authorization: Bearer $token";
}
curl_setopt_array($ch, [
    CURLOPT_URL => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => $method,
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_SSL_VERIFYPEER => false
]);
if (!empty($data)) {
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
}
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
echo "状态码: $status\n";
echo "响应: $response\n";
if ($error) {
    echo "错误: $error\n";
}
// 命令行使用方式
// php test_api.php method=POST url=http://localhost:8000/api/users data='{"name":"test"}' token=xxx

使用 PHPUnit 测试

<?php
use PHPUnit\Framework\TestCase;
class ApiTest extends TestCase {
    private $baseUrl = 'http://localhost:8000/api';
    private $client;
    protected function setUp(): void {
        $this->client = new Client([
            'base_uri' => $this->baseUrl,
            'timeout' => 10,
            'http_errors' => false
        ]);
    }
    public function testGetUsers() {
        $response = $this->client->get('/users');
        $this->assertEquals(200, $response->getStatusCode());
        $data = json_decode($response->getBody(), true);
        $this->assertArrayHasKey('users', $data);
    }
    public function testCreateUser() {
        $response = $this->client->post('/users', [
            'json' => [
                'name' => '测试用户',
                'email' => 'test@example.com'
            ]
        ]);
        $this->assertEquals(201, $response->getStatusCode());
        $data = json_decode($response->getBody(), true);
        $this->assertArrayHasKey('id', $data);
    }
}

最佳实践建议

  1. 统一封装:建议使用一个统一的请求封装类,方便维护
  2. 错误处理:始终检查 HTTP 状态码和错误信息
  3. 超时设置:设置合理的超时时间,避免请求挂起
  4. 日志记录:记录请求和响应的日志,便于调试
  5. 测试数据:预先准备测试数据,确保测试可重复
  6. 安全管理:不要在代码中硬编码敏感信息(API密钥等)

选择哪种方法取决于你的项目复杂度:

  • 简单测试 ➜ file_get_contents 或简单 cURL
  • 中等项目 ➜ 自定义封装类
  • 大型项目 ➜ GuzzleHttp 等成熟库
  • 自动化测试 ➜ PHPUnit + GuzzleHttp

抱歉,评论功能暂时关闭!