|
|
@@ -7,7 +7,13 @@ use common\components\delivery\services\adapter\FengniaoAdapter;
|
|
|
/**
|
|
|
* 蜂鸟适配器单元测试
|
|
|
*
|
|
|
- * 测试覆盖所有公开方法的业务逻辑、参数验证和响应处理
|
|
|
+ * 支持两种测试模式:
|
|
|
+ * 1. 模拟模式 - 使用虚假数据进行快速单元测试
|
|
|
+ * 2. 真实模式 - 向蜂鸟沙箱/正式环境发送真实请求
|
|
|
+ *
|
|
|
+ * 使用方式:
|
|
|
+ * - 单元测试(模拟模式):phpunit common/tests/unit/components/delivery/services/adapter/FengniaoAdapterTest.php
|
|
|
+ * - 集成测试(真实模式):phpunit common/tests/unit/components/delivery/services/adapter/FengniaoAdapterTest.php --use-real-api=true
|
|
|
*/
|
|
|
class FengniaoAdapterTest extends \PHPUnit\Framework\TestCase
|
|
|
{
|
|
|
@@ -17,15 +23,47 @@ class FengniaoAdapterTest extends \PHPUnit\Framework\TestCase
|
|
|
private $adapter;
|
|
|
|
|
|
/**
|
|
|
- * @var \PHPUnit\Framework\MockObject\MockObject
|
|
|
+ * 是否使用真实API
|
|
|
+ */
|
|
|
+ private $useRealApi = false;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 测试用商户ID
|
|
|
+ */
|
|
|
+ private const TEST_MERCHANT_ID = '204653075';
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 测试用访问令牌(沙箱环境)
|
|
|
*/
|
|
|
- private $httpClientMock;
|
|
|
+ private const TEST_ACCESS_TOKEN = ''; // 需要配置真实的访问令牌
|
|
|
|
|
|
protected function setUp(): void
|
|
|
{
|
|
|
+ // 从命令行参数或环境变量检查是否使用真实API
|
|
|
+ $this->useRealApi = getenv('USE_REAL_API') === 'true' ||
|
|
|
+ (isset($_SERVER['USE_REAL_API']) && $_SERVER['USE_REAL_API'] === 'true');
|
|
|
+
|
|
|
// 初始化适配器
|
|
|
- $this->adapter = new FengniaoAdapter('test-access-token');
|
|
|
- $this->adapter->setMerchantId('test-merchant-id');
|
|
|
+ $this->adapter = new FengniaoAdapter(self::TEST_ACCESS_TOKEN);
|
|
|
+ $this->adapter->setMerchantId(self::TEST_MERCHANT_ID);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 发送真实请求或返回模拟响应
|
|
|
+ *
|
|
|
+ * @param callable $realApiCall 真实API调用的回调函数
|
|
|
+ * @param array $mockResponse 模拟响应数据
|
|
|
+ * @return array 响应数据
|
|
|
+ */
|
|
|
+ private function executeApiCall(callable $realApiCall, array $mockResponse = null)
|
|
|
+ {
|
|
|
+ if ($this->useRealApi) {
|
|
|
+ // 真实API调用
|
|
|
+ return $realApiCall();
|
|
|
+ } else {
|
|
|
+ // 模拟模式:返回预定义的响应
|
|
|
+ return $mockResponse ?? [];
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -33,12 +71,11 @@ class FengniaoAdapterTest extends \PHPUnit\Framework\TestCase
|
|
|
*/
|
|
|
|
|
|
/**
|
|
|
- * 测试城市列表查询成功
|
|
|
+ * 测试城市列表查询
|
|
|
* @test
|
|
|
*/
|
|
|
- public function testCityListSuccess()
|
|
|
+ public function testCityList()
|
|
|
{
|
|
|
- // 模拟蜂鸟API的成功响应
|
|
|
$mockResponse = [
|
|
|
'code' => '200',
|
|
|
'msg' => 'success',
|
|
|
@@ -52,51 +89,24 @@ class FengniaoAdapterTest extends \PHPUnit\Framework\TestCase
|
|
|
'sign' => 'mock-signature'
|
|
|
];
|
|
|
|
|
|
- $this->assertEquals('200', $mockResponse['code']);
|
|
|
- $this->assertEquals('success', $mockResponse['msg']);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * ============= createOrder() 方法测试 =============
|
|
|
- */
|
|
|
-
|
|
|
- /**
|
|
|
- * 测试创建订单成功
|
|
|
- * @test
|
|
|
- */
|
|
|
- public function testCreateOrderSuccess()
|
|
|
- {
|
|
|
- $orderData = $this->getValidCreateOrderData();
|
|
|
-
|
|
|
- // 模拟蜂鸟API的成功响应
|
|
|
- $mockResponse = [
|
|
|
- 'code' => '200',
|
|
|
- 'msg' => 'success',
|
|
|
- 'business_data' => json_encode([
|
|
|
- 'order_id' => '300000211323129144'
|
|
|
- ]),
|
|
|
- 'sign' => 'mock-signature'
|
|
|
- ];
|
|
|
-
|
|
|
- $this->assertEquals('200', $mockResponse['code']);
|
|
|
- $respData = json_decode($mockResponse['business_data'], true);
|
|
|
- $this->assertNotEmpty($respData['order_id']);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 测试创建订单参数缺失
|
|
|
- * @test
|
|
|
- */
|
|
|
- public function testCreateOrderMissingParameters()
|
|
|
- {
|
|
|
- // 缺少必填参数的订单数据
|
|
|
- $incompleteData = [
|
|
|
- 'partner_order_code' => 'TEST_ORDER_001',
|
|
|
- // 缺少其他必填参数
|
|
|
- ];
|
|
|
-
|
|
|
- // 验证参数检查
|
|
|
- $this->assertEmpty($incompleteData['receiver_name'] ?? null);
|
|
|
+ $result = $this->executeApiCall(
|
|
|
+ function() { return $this->adapter->cityList(); },
|
|
|
+ $mockResponse
|
|
|
+ );
|
|
|
+
|
|
|
+ if ($this->useRealApi) {
|
|
|
+ // 真实API返回结果验证
|
|
|
+ $this->assertIsArray($result);
|
|
|
+ if (isset($result['code'])) {
|
|
|
+ $this->assertNotEmpty($result['code']);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 模拟响应验证
|
|
|
+ $this->assertEquals('200', $result['code']);
|
|
|
+ $this->assertEquals('success', $result['msg']);
|
|
|
+ $respData = json_decode($result['business_data'], true);
|
|
|
+ $this->assertNotEmpty($respData['cities']);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -104,14 +114,13 @@ class FengniaoAdapterTest extends \PHPUnit\Framework\TestCase
|
|
|
*/
|
|
|
|
|
|
/**
|
|
|
- * 测试获取运费报价成功
|
|
|
+ * 测试获取运费报价
|
|
|
* @test
|
|
|
*/
|
|
|
- public function testGetPriceSuccess()
|
|
|
+ public function testGetPrice()
|
|
|
{
|
|
|
$priceData = $this->getValidGetPriceData();
|
|
|
|
|
|
- // 模拟蜂鸟API的成功响应
|
|
|
$mockResponse = [
|
|
|
'code' => '200',
|
|
|
'msg' => 'success',
|
|
|
@@ -137,9 +146,70 @@ class FengniaoAdapterTest extends \PHPUnit\Framework\TestCase
|
|
|
'sign' => 'mock-signature'
|
|
|
];
|
|
|
|
|
|
- $this->assertEquals('200', $mockResponse['code']);
|
|
|
- $respData = json_decode($mockResponse['business_data'], true);
|
|
|
- $this->assertNotEmpty($respData['goods_infos']);
|
|
|
+ $result = $this->executeApiCall(
|
|
|
+ function() use ($priceData) { return $this->adapter->getPrice($priceData); },
|
|
|
+ $mockResponse
|
|
|
+ );
|
|
|
+
|
|
|
+ if ($this->useRealApi) {
|
|
|
+ // 真实API返回结果验证
|
|
|
+ $this->assertIsArray($result);
|
|
|
+ echo "\n[真实API响应] getPrice: " . json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
|
|
+ if (isset($result['code']) && $result['code'] == '200') {
|
|
|
+ $respData = json_decode($result['business_data'], true);
|
|
|
+ $this->assertIsArray($respData);
|
|
|
+ if (isset($respData['goods_infos'])) {
|
|
|
+ $this->assertIsArray($respData['goods_infos']);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 模拟响应验证
|
|
|
+ $this->assertEquals('200', $result['code']);
|
|
|
+ $respData = json_decode($result['business_data'], true);
|
|
|
+ $this->assertNotEmpty($respData['goods_infos']);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * ============= createOrder() 方法测试 =============
|
|
|
+ */
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 测试创建订单
|
|
|
+ * @test
|
|
|
+ */
|
|
|
+ public function testCreateOrder()
|
|
|
+ {
|
|
|
+ $orderData = $this->getValidCreateOrderData();
|
|
|
+
|
|
|
+ $mockResponse = [
|
|
|
+ 'code' => '200',
|
|
|
+ 'msg' => 'success',
|
|
|
+ 'business_data' => json_encode([
|
|
|
+ 'order_id' => '300000211323129144'
|
|
|
+ ]),
|
|
|
+ 'sign' => 'mock-signature'
|
|
|
+ ];
|
|
|
+
|
|
|
+ $result = $this->executeApiCall(
|
|
|
+ function() use ($orderData) { return $this->adapter->createOrder($orderData); },
|
|
|
+ $mockResponse
|
|
|
+ );
|
|
|
+
|
|
|
+ if ($this->useRealApi) {
|
|
|
+ // 真实API返回结果验证
|
|
|
+ $this->assertIsArray($result);
|
|
|
+ echo "\n[真实API响应] createOrder: " . json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
|
|
+ if (isset($result['code']) && $result['code'] == '200') {
|
|
|
+ $respData = json_decode($result['business_data'], true);
|
|
|
+ $this->assertNotEmpty($respData['order_id'] ?? null);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 模拟响应验证
|
|
|
+ $this->assertEquals('200', $result['code']);
|
|
|
+ $respData = json_decode($result['business_data'], true);
|
|
|
+ $this->assertNotEmpty($respData['order_id']);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -147,10 +217,10 @@ class FengniaoAdapterTest extends \PHPUnit\Framework\TestCase
|
|
|
*/
|
|
|
|
|
|
/**
|
|
|
- * 测试获取取消原因列表成功
|
|
|
+ * 测试获取取消原因列表
|
|
|
* @test
|
|
|
*/
|
|
|
- public function testGetCancelReasonListSuccess()
|
|
|
+ public function testGetCancelReasonList()
|
|
|
{
|
|
|
$mockResponse = [
|
|
|
'code' => '200',
|
|
|
@@ -166,22 +236,34 @@ class FengniaoAdapterTest extends \PHPUnit\Framework\TestCase
|
|
|
'sign' => 'mock-signature'
|
|
|
];
|
|
|
|
|
|
- $this->assertEquals('200', $mockResponse['code']);
|
|
|
- $respData = json_decode($mockResponse['business_data'], true);
|
|
|
- $this->assertCount(4, $respData['cancel_reason_list']);
|
|
|
- }
|
|
|
+ // 使用真实订单ID或合作订单号
|
|
|
+ $queryData = [
|
|
|
+ // 二选一:order_id 或 partner_order_code
|
|
|
+ // 'order_id' => '300000219758073736',
|
|
|
+ 'partner_order_code' => 'TEST_ORDER_' . time(),
|
|
|
+ ];
|
|
|
|
|
|
- /**
|
|
|
- * 测试获取取消原因列表 - 参数验证
|
|
|
- * @test
|
|
|
- */
|
|
|
- public function testGetCancelReasonListParameterValidation()
|
|
|
- {
|
|
|
- // 订单标识必填一个
|
|
|
- $invalidData = [];
|
|
|
-
|
|
|
- $this->assertEmpty($invalidData['order_id'] ?? null);
|
|
|
- $this->assertEmpty($invalidData['partner_order_code'] ?? null);
|
|
|
+ $result = $this->executeApiCall(
|
|
|
+ function() use ($queryData) { return $this->adapter->getCancelReasonList($queryData); },
|
|
|
+ $mockResponse
|
|
|
+ );
|
|
|
+
|
|
|
+ if ($this->useRealApi) {
|
|
|
+ // 真实API返回结果验证
|
|
|
+ $this->assertIsArray($result);
|
|
|
+ echo "\n[真实API响应] getCancelReasonList: " . json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
|
|
+ if (isset($result['code']) && $result['code'] == '200') {
|
|
|
+ $respData = json_decode($result['business_data'], true);
|
|
|
+ if (isset($respData['cancel_reason_list'])) {
|
|
|
+ $this->assertIsArray($respData['cancel_reason_list']);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 模拟响应验证
|
|
|
+ $this->assertEquals('200', $result['code']);
|
|
|
+ $respData = json_decode($result['business_data'], true);
|
|
|
+ $this->assertCount(4, $respData['cancel_reason_list']);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -189,10 +271,10 @@ class FengniaoAdapterTest extends \PHPUnit\Framework\TestCase
|
|
|
*/
|
|
|
|
|
|
/**
|
|
|
- * 测试订单取消成功
|
|
|
+ * 测试订单取消
|
|
|
* @test
|
|
|
*/
|
|
|
- public function testCancelOrderSuccess()
|
|
|
+ public function testCancelOrder()
|
|
|
{
|
|
|
$cancelData = $this->getValidCancelOrderData();
|
|
|
|
|
|
@@ -206,41 +288,27 @@ class FengniaoAdapterTest extends \PHPUnit\Framework\TestCase
|
|
|
'sign' => 'mock-signature'
|
|
|
];
|
|
|
|
|
|
- $this->assertEquals('200', $mockResponse['code']);
|
|
|
- $respData = json_decode($mockResponse['business_data'], true);
|
|
|
- $this->assertTrue($respData['result']);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 测试订单取消 - 商户取消
|
|
|
- * @test
|
|
|
- */
|
|
|
- public function testCancelOrderByMerchant()
|
|
|
- {
|
|
|
- $cancelData = [
|
|
|
- 'order_id' => '300000219758073736',
|
|
|
- 'order_cancel_role' => 1, // 商户取消
|
|
|
- 'order_cancel_code' => 32,
|
|
|
- 'order_cancel_other_reason' => '库存不足',
|
|
|
- ];
|
|
|
-
|
|
|
- $this->assertEquals(1, $cancelData['order_cancel_role']);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 测试订单取消 - 用户取消
|
|
|
- * @test
|
|
|
- */
|
|
|
- public function testCancelOrderByUser()
|
|
|
- {
|
|
|
- $cancelData = [
|
|
|
- 'order_id' => '300000219758073736',
|
|
|
- 'order_cancel_role' => 2, // 用户取消
|
|
|
- 'order_cancel_code' => 9,
|
|
|
- 'order_cancel_other_reason' => '临时不想要了',
|
|
|
- ];
|
|
|
-
|
|
|
- $this->assertEquals(2, $cancelData['order_cancel_role']);
|
|
|
+ $result = $this->executeApiCall(
|
|
|
+ function() use ($cancelData) { return $this->adapter->cancelOrder($cancelData); },
|
|
|
+ $mockResponse
|
|
|
+ );
|
|
|
+
|
|
|
+ if ($this->useRealApi) {
|
|
|
+ // 真实API返回结果验证
|
|
|
+ $this->assertIsArray($result);
|
|
|
+ echo "\n[真实API响应] cancelOrder: " . json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
|
|
+ if (isset($result['code']) && $result['code'] == '200') {
|
|
|
+ $respData = json_decode($result['business_data'], true);
|
|
|
+ if (isset($respData['result'])) {
|
|
|
+ $this->assertIsBool($respData['result']);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 模拟响应验证
|
|
|
+ $this->assertEquals('200', $result['code']);
|
|
|
+ $respData = json_decode($result['business_data'], true);
|
|
|
+ $this->assertTrue($respData['result']);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -248,10 +316,10 @@ class FengniaoAdapterTest extends \PHPUnit\Framework\TestCase
|
|
|
*/
|
|
|
|
|
|
/**
|
|
|
- * 测试预取消订单成功
|
|
|
+ * 测试预取消订单
|
|
|
* @test
|
|
|
*/
|
|
|
- public function testPreCancelOrderSuccess()
|
|
|
+ public function testPreCancelOrder()
|
|
|
{
|
|
|
$mockResponse = [
|
|
|
'code' => '200',
|
|
|
@@ -262,9 +330,27 @@ class FengniaoAdapterTest extends \PHPUnit\Framework\TestCase
|
|
|
'sign' => 'mock-signature'
|
|
|
];
|
|
|
|
|
|
- $this->assertEquals('200', $mockResponse['code']);
|
|
|
- $respData = json_decode($mockResponse['business_data'], true);
|
|
|
- $this->assertEquals(0, $respData['actual_cancel_cost_cent']);
|
|
|
+ $queryData = [
|
|
|
+ 'order_id' => '300000219758073736',
|
|
|
+ 'order_cancel_role' => 1,
|
|
|
+ 'order_cancel_code' => 32,
|
|
|
+ ];
|
|
|
+
|
|
|
+ $result = $this->executeApiCall(
|
|
|
+ function() use ($queryData) { return $this->adapter->preCancelOrder($queryData); },
|
|
|
+ $mockResponse
|
|
|
+ );
|
|
|
+
|
|
|
+ if ($this->useRealApi) {
|
|
|
+ // 真实API返回结果验证
|
|
|
+ $this->assertIsArray($result);
|
|
|
+ echo "\n[真实API响应] preCancelOrder: " . json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
|
|
+ } else {
|
|
|
+ // 模拟响应验证
|
|
|
+ $this->assertEquals('200', $result['code']);
|
|
|
+ $respData = json_decode($result['business_data'], true);
|
|
|
+ $this->assertEquals(0, $respData['actual_cancel_cost_cent']);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -272,10 +358,10 @@ class FengniaoAdapterTest extends \PHPUnit\Framework\TestCase
|
|
|
*/
|
|
|
|
|
|
/**
|
|
|
- * 测试添加小费成功
|
|
|
+ * 测试添加小费
|
|
|
* @test
|
|
|
*/
|
|
|
- public function testAddTipSuccess()
|
|
|
+ public function testAddTip()
|
|
|
{
|
|
|
$tipData = [
|
|
|
'order_id' => '300000215893560503',
|
|
|
@@ -292,31 +378,21 @@ class FengniaoAdapterTest extends \PHPUnit\Framework\TestCase
|
|
|
'sign' => 'mock-signature'
|
|
|
];
|
|
|
|
|
|
- $this->assertEquals('200', $mockResponse['code']);
|
|
|
- $respData = json_decode($mockResponse['business_data'], true);
|
|
|
- $this->assertTrue($respData['result']);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 测试添加小费 - 幂等性
|
|
|
- * @test
|
|
|
- */
|
|
|
- public function testAddTipIdempotency()
|
|
|
- {
|
|
|
- // 使用相同的 third_index_id 进行重复请求
|
|
|
- $tipData1 = [
|
|
|
- 'order_id' => '300000215893560503',
|
|
|
- 'third_index_id' => 1,
|
|
|
- 'add_tip_amount_cent' => 200,
|
|
|
- ];
|
|
|
-
|
|
|
- $tipData2 = [
|
|
|
- 'order_id' => '300000215893560503',
|
|
|
- 'third_index_id' => 1, // 相同的 ID
|
|
|
- 'add_tip_amount_cent' => 200,
|
|
|
- ];
|
|
|
-
|
|
|
- $this->assertEquals($tipData1['third_index_id'], $tipData2['third_index_id']);
|
|
|
+ $result = $this->executeApiCall(
|
|
|
+ function() use ($tipData) { return $this->adapter->addTip($tipData); },
|
|
|
+ $mockResponse
|
|
|
+ );
|
|
|
+
|
|
|
+ if ($this->useRealApi) {
|
|
|
+ // 真实API返回结果验证
|
|
|
+ $this->assertIsArray($result);
|
|
|
+ echo "\n[真实API响应] addTip: " . json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
|
|
+ } else {
|
|
|
+ // 模拟响应验证
|
|
|
+ $this->assertEquals('200', $result['code']);
|
|
|
+ $respData = json_decode($result['business_data'], true);
|
|
|
+ $this->assertTrue($respData['result']);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -324,10 +400,10 @@ class FengniaoAdapterTest extends \PHPUnit\Framework\TestCase
|
|
|
*/
|
|
|
|
|
|
/**
|
|
|
- * 测试获取订单详情成功
|
|
|
+ * 测试获取订单详情
|
|
|
* @test
|
|
|
*/
|
|
|
- public function testGetOrderDetailSuccess()
|
|
|
+ public function testGetOrderDetail()
|
|
|
{
|
|
|
$mockResponse = [
|
|
|
'code' => '200',
|
|
|
@@ -344,39 +420,35 @@ class FengniaoAdapterTest extends \PHPUnit\Framework\TestCase
|
|
|
'order_actual_amount_cent' => 950,
|
|
|
'order_tip_amount_cent' => 200,
|
|
|
'order_distance' => 5000,
|
|
|
- 'price_detail' => [
|
|
|
- 'start_price_cent' => 500,
|
|
|
- 'distance_price_cent' => 450,
|
|
|
- ]
|
|
|
]),
|
|
|
'sign' => 'mock-signature'
|
|
|
];
|
|
|
|
|
|
- $this->assertEquals('200', $mockResponse['code']);
|
|
|
- $respData = json_decode($mockResponse['business_data'], true);
|
|
|
- $this->assertEquals(2, $respData['order_status']);
|
|
|
- $this->assertNotEmpty($respData['carrier_driver_name']);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 测试获取订单详情 - 查询不同订单状态
|
|
|
- * @test
|
|
|
- */
|
|
|
- public function testGetOrderDetailMultipleStatus()
|
|
|
- {
|
|
|
- $statusList = [
|
|
|
- 0 => '订单生成',
|
|
|
- 1 => '运单生成成功',
|
|
|
- 20 => '骑手接单',
|
|
|
- 80 => '骑手到店',
|
|
|
- 2 => '配送中',
|
|
|
- 3 => '已完成',
|
|
|
- 4 => '已取消',
|
|
|
- 5 => '配送异常',
|
|
|
+ $queryData = [
|
|
|
+ 'order_id' => '300000211323129144',
|
|
|
];
|
|
|
|
|
|
- foreach ($statusList as $status => $desc) {
|
|
|
- $this->assertNotEmpty($desc);
|
|
|
+ $result = $this->executeApiCall(
|
|
|
+ function() use ($queryData) { return $this->adapter->getOrderDetail($queryData); },
|
|
|
+ $mockResponse
|
|
|
+ );
|
|
|
+
|
|
|
+ if ($this->useRealApi) {
|
|
|
+ // 真实API返回结果验证
|
|
|
+ $this->assertIsArray($result);
|
|
|
+ echo "\n[真实API响应] getOrderDetail: " . json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
|
|
+ if (isset($result['code']) && $result['code'] == '200') {
|
|
|
+ $respData = json_decode($result['business_data'], true);
|
|
|
+ $this->assertIsArray($respData);
|
|
|
+ if (isset($respData['order_status'])) {
|
|
|
+ $this->assertIsInt((int)$respData['order_status']);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 模拟响应验证
|
|
|
+ $this->assertEquals('200', $result['code']);
|
|
|
+ $respData = json_decode($result['business_data'], true);
|
|
|
+ $this->assertEquals(2, $respData['order_status']);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -385,10 +457,10 @@ class FengniaoAdapterTest extends \PHPUnit\Framework\TestCase
|
|
|
*/
|
|
|
|
|
|
/**
|
|
|
- * 测试获取骑手信息成功
|
|
|
+ * 测试获取骑手信息
|
|
|
* @test
|
|
|
*/
|
|
|
- public function testGetKnightInfoSuccess()
|
|
|
+ public function testGetKnightInfo()
|
|
|
{
|
|
|
$mockResponse = [
|
|
|
'code' => '200',
|
|
|
@@ -403,36 +475,33 @@ class FengniaoAdapterTest extends \PHPUnit\Framework\TestCase
|
|
|
'sign' => 'mock-signature'
|
|
|
];
|
|
|
|
|
|
- $this->assertEquals('200', $mockResponse['code']);
|
|
|
- $respData = json_decode($mockResponse['business_data'], true);
|
|
|
- $this->assertNotEmpty($respData['carrier_driver_name']);
|
|
|
- $this->assertNotEmpty($respData['carrier_driver_latitude']);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 测试获取骑手信息 - 返回高德坐标系
|
|
|
- * @test
|
|
|
- */
|
|
|
- public function testGetKnightInfoAMapCoordinate()
|
|
|
- {
|
|
|
- $mockResponse = [
|
|
|
- 'code' => '200',
|
|
|
- 'msg' => 'success',
|
|
|
- 'business_data' => json_encode([
|
|
|
- 'carrier_driver_latitude' => '39.9042', // 高德纬度
|
|
|
- 'carrier_driver_longitude' => '116.4074', // 高德经度
|
|
|
- ]),
|
|
|
+ $queryData = [
|
|
|
+ 'order_id' => '300000215893560503',
|
|
|
];
|
|
|
|
|
|
- $respData = json_decode($mockResponse['business_data'], true);
|
|
|
- // 验证坐标格式(高德地图坐标范围)
|
|
|
- $lat = (float)$respData['carrier_driver_latitude'];
|
|
|
- $lon = (float)$respData['carrier_driver_longitude'];
|
|
|
-
|
|
|
- $this->assertGreaterThanOrEqual(-90, $lat);
|
|
|
- $this->assertLessThanOrEqual(90, $lat);
|
|
|
- $this->assertGreaterThanOrEqual(-180, $lon);
|
|
|
- $this->assertLessThanOrEqual(180, $lon);
|
|
|
+ $result = $this->executeApiCall(
|
|
|
+ function() use ($queryData) { return $this->adapter->getKnightInfo($queryData); },
|
|
|
+ $mockResponse
|
|
|
+ );
|
|
|
+
|
|
|
+ if ($this->useRealApi) {
|
|
|
+ // 真实API返回结果验证
|
|
|
+ $this->assertIsArray($result);
|
|
|
+ echo "\n[真实API响应] getKnightInfo: " . json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
|
|
+ if (isset($result['code']) && $result['code'] == '200') {
|
|
|
+ $respData = json_decode($result['business_data'], true);
|
|
|
+ if (isset($respData['carrier_driver_latitude'])) {
|
|
|
+ $lat = (float)$respData['carrier_driver_latitude'];
|
|
|
+ $this->assertGreaterThanOrEqual(-90, $lat);
|
|
|
+ $this->assertLessThanOrEqual(90, $lat);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 模拟响应验证
|
|
|
+ $this->assertEquals('200', $result['code']);
|
|
|
+ $respData = json_decode($result['business_data'], true);
|
|
|
+ $this->assertNotEmpty($respData['carrier_driver_name']);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -445,7 +514,7 @@ class FengniaoAdapterTest extends \PHPUnit\Framework\TestCase
|
|
|
private function getValidCreateOrderData(): array
|
|
|
{
|
|
|
return [
|
|
|
- 'partner_order_code' => 'TEST_ORDER_' . time(),
|
|
|
+ 'partner_order_code' => 'TEST_ORDER_' . time() . '_' . uniqid(),
|
|
|
'receiver_primary_phone' => '13800000000',
|
|
|
'receiver_name' => '张三',
|
|
|
'receiver_latitude' => 39.9042,
|
|
|
@@ -475,7 +544,7 @@ class FengniaoAdapterTest extends \PHPUnit\Framework\TestCase
|
|
|
],
|
|
|
],
|
|
|
'order_type' => 1,
|
|
|
- 'chain_store_id' => 204653075,
|
|
|
+ 'chain_store_id' => self::TEST_MERCHANT_ID,
|
|
|
'order_remark' => '请轻拿轻放',
|
|
|
];
|
|
|
}
|
|
|
@@ -486,8 +555,8 @@ class FengniaoAdapterTest extends \PHPUnit\Framework\TestCase
|
|
|
private function getValidGetPriceData(): array
|
|
|
{
|
|
|
return [
|
|
|
- 'partner_order_code' => 'TEST_PRICE_' . time(),
|
|
|
- 'chain_store_id' => 204653075,
|
|
|
+ 'partner_order_code' => 'TEST_PRICE_' . time() . '_' . uniqid(),
|
|
|
+ 'chain_store_id' => self::TEST_MERCHANT_ID,
|
|
|
'position_source' => 3,
|
|
|
'receiver_address' => '北京市朝阳区建国门外大街1号',
|
|
|
'receiver_latitude' => 39.9042,
|
|
|
@@ -529,55 +598,46 @@ class FengniaoAdapterTest extends \PHPUnit\Framework\TestCase
|
|
|
* 测试API错误响应处理
|
|
|
* @test
|
|
|
*/
|
|
|
- public function testApiErrorResponse()
|
|
|
+ public function testApiErrorResponseHandling()
|
|
|
{
|
|
|
- $errorResponse = [
|
|
|
- 'code' => '400',
|
|
|
- 'msg' => 'Invalid parameters',
|
|
|
- 'business_data' => null,
|
|
|
- ];
|
|
|
-
|
|
|
- $this->assertNotEquals('200', $errorResponse['code']);
|
|
|
- $this->assertNull($errorResponse['business_data']);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 测试业务数据JSON解析失败
|
|
|
- * @test
|
|
|
- */
|
|
|
- public function testBusinessDataJsonParseFail()
|
|
|
- {
|
|
|
- $invalidResponse = [
|
|
|
- 'code' => '200',
|
|
|
- 'msg' => 'success',
|
|
|
- 'business_data' => 'invalid json data',
|
|
|
- ];
|
|
|
-
|
|
|
- $respData = json_decode($invalidResponse['business_data'], true);
|
|
|
- $this->assertNull($respData); // 解析失败返回 null
|
|
|
+ if ($this->useRealApi) {
|
|
|
+ // 真实模式:发送错误的参数
|
|
|
+ $invalidData = [
|
|
|
+ 'partner_order_code' => '', // 空的订单号
|
|
|
+ 'receiver_name' => '', // 空的收货人名称
|
|
|
+ ];
|
|
|
+
|
|
|
+ $result = $this->adapter->createOrder($invalidData);
|
|
|
+
|
|
|
+ // 应该返回错误响应
|
|
|
+ $this->assertIsArray($result);
|
|
|
+ echo "\n[真实API响应] 错误处理测试: " . json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
|
|
+ } else {
|
|
|
+ // 模拟模式:简单的响应验证
|
|
|
+ $errorResponse = [
|
|
|
+ 'code' => '400',
|
|
|
+ 'msg' => 'Invalid parameters',
|
|
|
+ 'business_data' => null,
|
|
|
+ ];
|
|
|
+
|
|
|
+ $this->assertNotEquals('200', $errorResponse['code']);
|
|
|
+ $this->assertNull($errorResponse['business_data']);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * ============= 必填参数验证测试 =============
|
|
|
+ * ============= 集成测试帮助方法 =============
|
|
|
*/
|
|
|
|
|
|
/**
|
|
|
- * 测试订单标识参数验证(二选一)
|
|
|
- * @test
|
|
|
+ * 输出测试提示信息
|
|
|
*/
|
|
|
- public function testOrderIdentifierParameterValidation()
|
|
|
+ protected function tearDown(): void
|
|
|
{
|
|
|
- // 只有 order_id
|
|
|
- $data1 = ['order_id' => '300000219758073736'];
|
|
|
- $this->assertNotEmpty($data1['order_id']);
|
|
|
-
|
|
|
- // 只有 partner_order_code
|
|
|
- $data2 = ['partner_order_code' => 'ORDER_2024_001'];
|
|
|
- $this->assertNotEmpty($data2['partner_order_code']);
|
|
|
-
|
|
|
- // 两个都缺失(无效)
|
|
|
- $data3 = [];
|
|
|
- $this->assertEmpty($data3['order_id'] ?? null);
|
|
|
- $this->assertEmpty($data3['partner_order_code'] ?? null);
|
|
|
+ if ($this->useRealApi) {
|
|
|
+ echo "\n========================================";
|
|
|
+ echo "\n✓ 真实API测试已执行";
|
|
|
+ echo "\n========================================\n";
|
|
|
+ }
|
|
|
}
|
|
|
}
|