Files
ECShopX/tests/ItemsCategoryFrontDisplayTest.php
2026-03-27 18:01:17 +08:00

261 lines
12 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* 计划:.tasks/plans/items-category-front-display.md TODO-0
* 验收用例 RED实体 is_show_front 读写、Repository 映射、FrontApi getCategoryList filter 含 is_show_front=>1。
* TC7后台列表不过滤、TC8迁移历史数据为手工或后续补充。
*/
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Mapping\ClassMetadata;
use GoodsBundle\Entities\ItemsCategory;
use GoodsBundle\Repositories\ItemsCategoryRepository;
use GoodsBundle\Http\FrontApi\V1\Action\Category;
use GoodsBundle\ApiServices\ItemsCategoryService as ApiServicesItemsCategoryService;
use EspierBundle\Services\Bus\TestBus;
use Illuminate\Http\Request;
class ItemsCategoryFrontDisplayTest extends TestCase
{
protected function setUp(): void
{
parent::setUp();
TestBus::resetLastPostData();
}
/**
* TC1/TC2实体 ItemsCategory 具备 is_show_front 的 getter/setter且可读写。
* #given 实体未实现 is_show_front 时
* #when 调用 getIsShowFront/setIsShowFront
* #then 当前 RED实体无 getIsShowFront/setIsShowFront测试失败。
*/
public function testEntityHasIsShowFrontGetterAndSetter(): void
{
$entity = new ItemsCategory();
$entity->setIsShowFront(0);
$this->assertSame(0, $entity->getIsShowFront());
$entity->setIsShowFront(1);
$this->assertSame(1, $entity->getIsShowFront());
}
/**
* Repository getColumnNamesData 返回数组包含 is_show_frontTC1TC4 读路径)。
* #given 实体有 getIsShowFront 时getColumnNamesData 应包含 is_show_front
* #when 用带 getIsShowFront 的 stub 调用 getColumnNamesData反射不连 DB
* #then 当前 REDgetColumnNamesData 未返回 is_show_front。
*/
public function testRepositoryGetColumnNamesDataIncludesIsShowFront(): void
{
$entity = new class extends ItemsCategory {
public $is_show_front = 1;
public function getIsShowFront() { return $this->is_show_front; }
};
$repo = $this->createRepositoryWithoutDb();
$ref = new \ReflectionClass($repo);
$method = $ref->getMethod('getColumnNamesData');
$method->setAccessible(true);
$data = $method->invoke($repo, $entity);
$this->assertArrayHasKey('is_show_front', $data, 'getColumnNamesData must include is_show_front (TC1TC4)');
$this->assertSame(1, $data['is_show_front']);
}
/**
* Repository setColumnNamesData 将 data['is_show_front'] 写入实体TC1TC4 写路径)。
* #given 传入 data 含 is_show_front
* #when 调用 setColumnNamesData反射后读取实体
* #then 当前 REDsetColumnNamesData 未映射 is_show_front 或实体无 getter。
*/
public function testRepositorySetColumnNamesDataMapsIsShowFront(): void
{
$entity = new class extends ItemsCategory {
public $is_show_front = 1;
public function getIsShowFront() { return $this->is_show_front; }
public function setIsShowFront($v) { $this->is_show_front = $v; return $this; }
};
$repo = $this->createRepositoryWithoutDb();
$ref = new \ReflectionClass($repo);
$method = $ref->getMethod('setColumnNamesData');
$method->setAccessible(true);
$data = [
'company_id' => 1,
'category_name' => 'Test',
'parent_id' => 0,
'is_show_front' => 0,
];
$method->invoke($repo, $entity, $data);
$this->assertSame(0, $entity->getIsShowFront(), 'setColumnNamesData must set is_show_front (TC1TC4)');
}
/**
* TC1后台创建时 form 含 is_show_front=0ApiServices saveItemsCategory 写入时传给 Repository create。
* #given ApiServices 使用 mock Repository 与 mock Connection
* #when 调用 saveItemsCategoryform 中含 is_show_front=0
* #then repository create() 被调用且参数包含 is_show_front=>0
*/
public function testCreateCategoryPassesIsShowFrontToRepositoryWhenPresent(): void
{
$mockDispatcher = $this->getMockBuilder(\Illuminate\Contracts\Events\Dispatcher::class)->getMock();
$mockDispatcher->method('dispatch')->willReturn(null);
$this->app->instance('events', $mockDispatcher);
$createParams = null;
$mockRepo = $this->getMockBuilder(ItemsCategoryRepository::class)->disableOriginalConstructor()->getMock();
$mockRepo->method('create')->willReturnCallback(function ($params) use (&$createParams) {
$createParams = $params;
return ['category_id' => 1, 'path' => ''];
});
$mockRepo->method('updateOneBy')->willReturn(true);
$mockManager = $this->getMockBuilder(\stdClass::class)->addMethods(['getRepository'])->getMock();
$mockManager->method('getRepository')->with(ItemsCategory::class)->willReturn($mockRepo);
$mockConn = $this->getMockBuilder(\stdClass::class)->addMethods(['beginTransaction', 'commit', 'rollBack'])->getMock();
$mockConn->method('beginTransaction')->willReturn(null);
$mockConn->method('commit')->willReturn(null);
$mockRegistry = $this->getMockBuilder(\stdClass::class)->addMethods(['getManager', 'getConnection'])->getMock();
$mockRegistry->method('getManager')->with('default')->willReturn($mockManager);
$mockRegistry->method('getConnection')->with('default')->willReturn($mockConn);
$this->app->instance('registry', $mockRegistry);
$service = new ApiServicesItemsCategoryService();
$form = [
[
'category_name' => 'TC1',
'sort' => 0,
'image_url' => '',
'is_show_front' => 0,
],
];
$service->saveItemsCategory($form, 1, 1);
$this->assertNotNull($createParams, 'create() must be called (TC1)');
$this->assertArrayHasKey('is_show_front', $createParams, 'create params must include is_show_front when provided (TC1)');
$this->assertSame(0, $createParams['is_show_front']);
}
/**
* TC2后台创建时 form 不传 is_show_frontApiServices 不写入该字段,由 DB 默认 1。
* #given ApiServices 使用 mock Repository
* #when 调用 saveItemsCategoryform 中不含 is_show_front
* #then repository create() 被调用且参数不包含 is_show_front
*/
public function testCreateCategoryOmitsIsShowFrontWhenNotProvided(): void
{
$mockDispatcher = $this->getMockBuilder(\Illuminate\Contracts\Events\Dispatcher::class)->getMock();
$mockDispatcher->method('dispatch')->willReturn(null);
$this->app->instance('events', $mockDispatcher);
$createParams = null;
$mockRepo = $this->getMockBuilder(ItemsCategoryRepository::class)->disableOriginalConstructor()->getMock();
$mockRepo->method('create')->willReturnCallback(function ($params) use (&$createParams) {
$createParams = $params;
return ['category_id' => 1, 'path' => ''];
});
$mockRepo->method('updateOneBy')->willReturn(true);
$mockManager = $this->getMockBuilder(\stdClass::class)->addMethods(['getRepository'])->getMock();
$mockManager->method('getRepository')->with(ItemsCategory::class)->willReturn($mockRepo);
$mockConn = $this->getMockBuilder(\stdClass::class)->addMethods(['beginTransaction', 'commit', 'rollBack'])->getMock();
$mockConn->method('beginTransaction')->willReturn(null);
$mockConn->method('commit')->willReturn(null);
$mockRegistry = $this->getMockBuilder(\stdClass::class)->addMethods(['getManager', 'getConnection'])->getMock();
$mockRegistry->method('getManager')->with('default')->willReturn($mockManager);
$mockRegistry->method('getConnection')->with('default')->willReturn($mockConn);
$this->app->instance('registry', $mockRegistry);
$service = new ApiServicesItemsCategoryService();
$form = [
[
'category_name' => 'TC2',
'sort' => 0,
'image_url' => '',
],
];
$service->saveItemsCategory($form, 1, 1);
$this->assertNotNull($createParams, 'create() must be called (TC2)');
$this->assertArrayNotHasKey('is_show_front', $createParams, 'create params must not include is_show_front when not provided so DB default 1 applies (TC2)');
}
/**
* TC3后台更新时 body 传 is_show_front=0ApiServices updateOneBy 将 data 透传给 Repository。
* #given ApiServices 使用 mock Repository
* #when 调用 updateOneBydata 中含 is_show_front=0
* #then repository updateOneBy() 被调用且第二个参数包含 is_show_front=>0
*/
public function testUpdateCategoryPassesIsShowFrontZeroToRepository(): void
{
$updateData = null;
$mockRepo = $this->getMockBuilder(ItemsCategoryRepository::class)->disableOriginalConstructor()->getMock();
$mockRepo->method('updateOneBy')->willReturnCallback(function ($filter, $data) use (&$updateData) {
$updateData = $data;
return ['category_id' => 1, 'is_show_front' => 0];
});
$mockRepo->method('findOneBy')->willReturn(new ItemsCategory());
$mockManager = $this->getMockBuilder(\stdClass::class)->addMethods(['getRepository'])->getMock();
$mockManager->method('getRepository')->with(ItemsCategory::class)->willReturn($mockRepo);
$mockRegistry = $this->getMockBuilder(\stdClass::class)->addMethods(['getManager'])->getMock();
$mockRegistry->method('getManager')->with('default')->willReturn($mockManager);
$this->app->instance('registry', $mockRegistry);
$service = new ApiServicesItemsCategoryService();
$service->updateOneBy(
['category_id' => 1, 'company_id' => 1],
['category_name' => 'Updated', 'is_show_front' => 0]
);
$this->assertNotNull($updateData, 'updateOneBy must be called (TC3)');
$this->assertArrayHasKey('is_show_front', $updateData, 'update data must include is_show_front when provided (TC3)');
$this->assertSame(0, $updateData['is_show_front']);
}
/**
* TC5/TC6FrontApi getCategoryList 调用 getItemsCategory 时 filter 含 is_show_front=>1。
* #given 使用 TestBus 捕获 post payload并 mock registry 避免 DB
* #when 调用 Category::getCategoryList(Request) 且 config goods 使用 test bus
* #then 当前 REDgetCategoryList 未在 filter 中加 is_show_front=>1。
*/
public function testFrontApiGetCategoryListPassesFilterWithIsShowFrontOne(): void
{
config(['services.goods' => ['rpc_type' => 'test', 'base_url' => '', 'sign' => '123']]);
$this->bindMockRegistryToAvoidDb();
$request = Request::create('/h5app/wxapp/goods/category', 'GET');
$request->replace(['auth' => ['company_id' => 1]]);
$request->setUserResolver(function () { return null; });
$controller = new Category();
$controller->getCategoryList($request);
$captured = TestBus::getLastPostData();
$this->assertNotNull($captured, 'getCategoryList must call Bus post (TC5/TC6)');
$this->assertArrayHasKey('filter', $captured);
$this->assertArrayHasKey('is_show_front', $captured['filter'], 'FrontApi getCategoryList filter must include is_show_front=>1 (TC5/TC6)');
$this->assertSame(1, $captured['filter']['is_show_front']);
}
private function createRepositoryWithoutDb(): ItemsCategoryRepository
{
$mockEm = $this->getMockBuilder(EntityManagerInterface::class)->getMock();
$metadata = new ClassMetadata(ItemsCategory::class);
return new ItemsCategoryRepository($mockEm, $metadata);
}
private function bindMockRegistryToAvoidDb(): void
{
$mockRepo = $this->getMockBuilder(ItemsCategoryRepository::class)->disableOriginalConstructor()->getMock();
$mockManager = $this->getMockBuilder(\stdClass::class)->addMethods(['getRepository'])->getMock();
$mockManager->method('getRepository')->with(ItemsCategory::class)->willReturn($mockRepo);
$mockRegistry = $this->getMockBuilder(\stdClass::class)->addMethods(['getManager'])->getMock();
$mockRegistry->method('getManager')->with('default')->willReturn($mockManager);
$this->app->instance('registry', $mockRegistry);
}
}