This commit is contained in:
Kris
2026-03-27 18:01:17 +08:00
parent 86c2d549e2
commit f439bfffe8
450 changed files with 63870 additions and 1408 deletions

View File

@@ -0,0 +1,260 @@
<?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);
}
}