15812, 'child_item_code' => 'BD-RS-43', 'lot_prefix' => 'RS', 'part_type' => '마감재', 'category' => 'guideRail', 'material_type' => 'SUS', 'length_mm' => 4300, 'qty' => 2, ]; } // ───────────────────────────────────────────────── // fromArray + toArray 라운드트립 // ───────────────────────────────────────────────── public function test_from_array_creates_dto(): void { $entry = DynamicBomEntry::fromArray($this->validData()); $this->assertEquals(15812, $entry->child_item_id); $this->assertEquals('BD-RS-43', $entry->child_item_code); $this->assertEquals('RS', $entry->lot_prefix); $this->assertEquals('마감재', $entry->part_type); $this->assertEquals('guideRail', $entry->category); $this->assertEquals('SUS', $entry->material_type); $this->assertEquals(4300, $entry->length_mm); $this->assertEquals(2, $entry->qty); } public function test_to_array_round_trip(): void { $data = $this->validData(); $entry = DynamicBomEntry::fromArray($data); $this->assertEquals($data, $entry->toArray()); } public function test_to_array_list(): void { $entries = [ DynamicBomEntry::fromArray($this->validData()), DynamicBomEntry::fromArray(array_merge($this->validData(), [ 'child_item_id' => 15813, 'child_item_code' => 'BD-RM-43', 'lot_prefix' => 'RM', 'part_type' => '본체', ])), ]; $list = DynamicBomEntry::toArrayList($entries); $this->assertCount(2, $list); $this->assertEquals('BD-RS-43', $list[0]['child_item_code']); $this->assertEquals('BD-RM-43', $list[1]['child_item_code']); } // ───────────────────────────────────────────────── // 유효한 카테고리 // ───────────────────────────────────────────────── /** * @dataProvider validCategoryProvider */ public function test_valid_categories(string $category): void { $data = array_merge($this->validData(), ['category' => $category]); $entry = DynamicBomEntry::fromArray($data); $this->assertEquals($category, $entry->category); } public static function validCategoryProvider(): array { return [ 'guideRail' => ['guideRail'], 'bottomBar' => ['bottomBar'], 'shutterBox' => ['shutterBox'], 'smokeBarrier' => ['smokeBarrier'], ]; } // ───────────────────────────────────────────────── // 필수 필드 누락 검증 // ───────────────────────────────────────────────── /** * @dataProvider requiredFieldProvider */ public function test_missing_required_field_throws(string $field): void { $data = $this->validData(); unset($data[$field]); $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage("'{$field}' is required"); DynamicBomEntry::fromArray($data); } public static function requiredFieldProvider(): array { return [ 'child_item_id' => ['child_item_id'], 'child_item_code' => ['child_item_code'], 'lot_prefix' => ['lot_prefix'], 'part_type' => ['part_type'], 'category' => ['category'], 'material_type' => ['material_type'], 'length_mm' => ['length_mm'], 'qty' => ['qty'], ]; } // ───────────────────────────────────────────────── // 값 제약 검증 // ───────────────────────────────────────────────── public function test_invalid_child_item_id_throws(): void { $data = array_merge($this->validData(), ['child_item_id' => 0]); $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('child_item_id must be positive'); DynamicBomEntry::fromArray($data); } public function test_invalid_category_throws(): void { $data = array_merge($this->validData(), ['category' => 'invalidCategory']); $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('category must be one of'); DynamicBomEntry::fromArray($data); } public function test_zero_qty_throws(): void { $data = array_merge($this->validData(), ['qty' => 0]); $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('qty must be positive'); DynamicBomEntry::fromArray($data); } public function test_negative_qty_throws(): void { $data = array_merge($this->validData(), ['qty' => -1]); $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('qty must be positive'); DynamicBomEntry::fromArray($data); } // ───────────────────────────────────────────────── // float qty 허용 // ───────────────────────────────────────────────── public function test_float_qty_allowed(): void { $data = array_merge($this->validData(), ['qty' => 1.5]); $entry = DynamicBomEntry::fromArray($data); $this->assertEquals(1.5, $entry->qty); } }