本文目录导读:

在 PHP 中,“数据提供器”(Data Provider)通常出现在单元测试(PHPUnit)或表单验证场景中,这里我主要介绍 PHPUnit 中最常用的数据提供器写法,以及简单的自定义数据提供器实现。
PHPUnit 数据提供器
这是最常用的场景,用于给测试方法批量提供测试数据。
基础用法
<?php
use PHPUnit\Framework\TestCase;
class CalculatorTest extends TestCase
{
/**
* @dataProvider additionProvider
*/
public function testAddition($a, $b, $expected)
{
$calculator = new Calculator();
$this->assertEquals($expected, $calculator->add($a, $b));
}
// 数据提供器方法
public static function additionProvider(): array
{
return [
'基础加法' => [1, 2, 3],
'零加数字' => [0, 5, 5],
'负数相加' => [-1, -2, -3],
'小数相加' => [1.5, 2.5, 4.0],
];
}
}
使用命名键(推荐)
class UserTest extends TestCase
{
/**
* @dataProvider userDataProvider
*/
public function testUserValidation($name, $email, $age, $expectValid)
{
$user = new User($name, $email, $age);
$this->assertEquals($expectValid, $user->validate());
}
public static function userDataProvider(): array
{
return [
'正常用户' => ['张三', 'zhangsan@example.com', 25, true],
'邮件格式错误' => ['李四', 'invalidemail', 30, false],
'年龄过小' => ['王五', 'wang@example.com', 17, false],
'名称为空' => ['', 'test@example.com', 25, false],
];
}
}
带迭代器的数据提供器(处理大量数据)
class LargeDataSetTest extends TestCase
{
/**
* @dataProvider largeDataProvider
*/
public function testProcessData($data)
{
// 处理大数据
$this->assertIsString($data);
}
public static function largeDataProvider(): iterable
{
// 使用生成器,避免内存消耗过大
for ($i = 0; $i < 10000; $i++) {
yield "数据{$i}" => ["value{$i}"];
}
}
}
外部文件数据源
class CsvDataTest extends TestCase
{
/**
* @dataProvider csvDataProvider
*/
public function testWithCsvData($row1, $row2)
{
// 测试逻辑
}
public static function csvDataProvider(): array
{
$data = [];
$file = fopen(__DIR__ . '/test_data.csv', 'r');
while (($row = fgetcsv($file)) !== false) {
$data[] = $row;
}
fclose($file);
return $data;
}
}
实现自定义的数据提供器(类)
如果需要在业务代码中实现类似"数据提供器"的组件:
<?php
interface DataProviderInterface
{
public function getData(): array;
}
class UserDataProvider implements DataProviderInterface
{
public function getData(): array
{
// 从数据库或文件加载用户数据
return [
['id' => 1, 'name' => '张三', 'email' => 'zhangsan@example.com'],
['id' => 2, 'name' => '李四', 'email' => 'lisi@example.com'],
];
}
}
class UserService
{
private DataProviderInterface $dataProvider;
public function __construct(DataProviderInterface $dataProvider)
{
$this->dataProvider = $dataProvider;
}
public function processUsers(): array
{
$result = [];
$users = $this->dataProvider->getData();
foreach ($users as $userData) {
// 处理用户数据
$result[] = [
'display_name' => strtoupper($userData['name']),
'email_valid' => filter_var($userData['email'], FILTER_VALIDATE_EMAIL) !== false
];
}
return $result;
}
}
带类型约束的数据提供器(PHP 8+ 特性)
<?php
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
class AdvancedTest extends TestCase
{
#[DataProvider('mathDataProvider')]
public function testMathOperation(float $a, float $b, float $expected): void
{
// PHP 8 使用注解风格
$result = $a * $b;
$this->assertEquals($expected, $result);
}
public static function mathDataProvider(): array
{
return [
'整数乘法' => [2, 3, 6],
'小数乘法' => [2.5, 4, 10.0],
'分数乘法' => [0.5, 0.5, 0.25],
];
}
}
注意事项
- 数据提供器是 static 方法:必须是 public static
- 返回类型:必须返回
array或iterable - 测试执行次数:每个数据集执行一次测试方法
- 命名键作用:失败时在控制台显示更友好的提示
- 内存管理:大量数据建议使用生成器
快速示例总结
class ApiTest extends TestCase
{
use DataProviderTrait; // 自定义Trait
/**
* @dataProvider apiDataProvider
*/
public function testApiCall($method, $url, $expectedStatus)
{
$response = $this->makeRequest($method, $url);
$this->assertEquals($expectedStatus, $response->getStatusCode());
}
public static function apiDataProvider(): array
{
return [
'GET请求' => ['GET', '/api/user', 200],
'POST请求' => ['POST', '/api/user', 201],
'PUT请求' => ['PUT', '/api/user/1', 200],
'DELETE请求' => ['DELETE', '/api/user/1', 204],
];
}
private function makeRequest($method, $url)
{
// 模拟请求逻辑
return (object) ['getStatusCode' => function() { return 200; }];
}
}
数据提供器让测试代码更简洁、易维护,是 PHP 单元测试中非常有用的工具,根据场景选择合适的方式即可。