@@ -352,48 +352,107 @@ package state
352352
353353import (
354354 " testing"
355- " log"
356355)
357356
358- // TestStatePattern 模拟客户端操作自动售货机
359- func TestStatePattern (t *testing .T ) {
360- // 1. 初始化售货机,只有 1 件商品,价格 10 元
361- vendingMachine := NewVendingMachine (1 , 10 )
362-
363- // 2. 正常购买流程
364- t.Log (" --- 第一次购买 ---" )
365-
366- err := vendingMachine.RequestItem () // 选中商品
367- if err != nil { log.Fatal (err) }
368-
369- err = vendingMachine.InsertMoney (10 ) // 投币
370- if err != nil { log.Fatal (err) }
357+ // 客户端
358+ // 单元测试
371359
372- err = vendingMachine.DispenseItem () // 出货
373- if err != nil { log.Fatal (err) }
374-
375- t.Log (" 第一次购买完成" )
376-
377- // 3. 尝试购买空售货机
378- t.Log (" \n --- 第二次购买(缺货)---" )
379-
380- err = vendingMachine.RequestItem () // 尝试选中
381- if err != nil {
382- t.Logf (" 预期错误: %s " , err.Error ())
383- }
384-
385- // 4. 补货
386- t.Log (" \n --- 补货 ---" )
387- err = vendingMachine.AddItem (2 )
388- if err != nil { log.Fatal (err) }
389-
390- t.Log (" 补货完成,可以继续购买" )
391-
392- // 验证状态是否恢复
393- err = vendingMachine.RequestItem ()
394- if err == nil {
395- t.Log (" 成功再次选中商品" )
396- }
360+ // TestStatePattern 模拟客户端操作自动售货机
361+ func TestVendingMachine (t *testing .T ) {
362+ // 场景 1: 正常购买流程 (Happy Path)
363+ t.Run (" HappyPathPurchaseSuccess" , func (t *testing.T ) {
364+ // Arrange: 初始化 1 个商品,价格 10 元
365+ vm := NewVendingMachine (1 , 10 )
366+
367+ // Act & Assert 1: 请求商品
368+ if err := vm.RequestItem (); err != nil {
369+ t.Fatalf (" 预期请求成功,但返回错误: %v " , err)
370+ }
371+
372+ // Act & Assert 2: 投入不足的金额 (测试中间逻辑)
373+ if err := vm.InsertMoney (5 ); err == nil {
374+ t.Fatal (" 预期金额不足报错,但未报错" )
375+ }
376+
377+ // Act & Assert 3: 投入足额金额
378+ if err := vm.InsertMoney (10 ); err != nil {
379+ t.Fatalf (" 预期投币成功,但返回错误: %v " , err)
380+ }
381+
382+ // Act & Assert 4: 出货
383+ if err := vm.DispenseItem (); err != nil {
384+ t.Fatalf (" 预期出货成功,但返回错误: %v " , err)
385+ }
386+
387+ // 验证副作用:库存应为 0
388+ if vm.itemCount != 0 {
389+ t.Errorf (" 预期库存为 0, 实际为 %d " , vm.itemCount )
390+ }
391+ })
392+
393+ // 场景 2: 缺货流程 (Out of Stock)
394+ t.Run (" OutOfStockFailure" , func (t *testing.T ) {
395+ // Arrange: 初始化 0 个商品
396+ vm := NewVendingMachine (0 , 10 )
397+
398+ // Act
399+ err := vm.RequestItem ()
400+
401+ // Assert
402+ if err == nil {
403+ t.Error (" 预期缺货报错,但返回了 nil" )
404+ }
405+ expectedErr := " 缺货中,请勿选择" // 这里假设具体的错误信息
406+ if err.Error () != expectedErr {
407+ t.Logf (" 收到预期内的错误: %v " , err) // 只要报错就行,具体信息如果不严格匹配可以用 Logf
408+ }
409+ })
410+
411+ // 场景 3: 状态流转限制 (非法操作)
412+ t.Run (" InvalidStateTransition" , func (t *testing.T ) {
413+ vm := NewVendingMachine (1 , 10 )
414+
415+ // 未选择商品直接投币
416+ err := vm.InsertMoney (10 )
417+ if err == nil {
418+ t.Error (" 预期报错'请先选择商品',但操作成功了" )
419+ }
420+
421+ // 未投币直接出货
422+ err = vm.RequestItem () // 先选中
423+ if err != nil {
424+ t.Fatal (err)
425+ }
426+
427+ err = vm.DispenseItem () // 未投币直接出货
428+ if err == nil {
429+ t.Error (" 预期报错'请先支付',但操作成功了" )
430+ }
431+ })
432+
433+ // 场景 4: 补货测试
434+ t.Run (" RestockSuccess" , func (t *testing.T ) {
435+ vm := NewVendingMachine (0 , 10 )
436+
437+ // 初始状态应无法购买
438+ if err := vm.RequestItem (); err == nil {
439+ t.Fatal (" 初始应缺货" )
440+ }
441+
442+ // 补货
443+ if err := vm.AddItem (5 ); err != nil {
444+ t.Fatalf (" 补货失败: %v " , err)
445+ }
446+
447+ // 补货后应能购买
448+ if err := vm.RequestItem (); err != nil {
449+ t.Errorf (" 补货后预期可以购买,但报错: %v " , err)
450+ }
451+
452+ if vm.itemCount != 5 {
453+ t.Errorf (" 预期库存 5, 实际 %d " , vm.itemCount )
454+ }
455+ })
397456}
398457```
399458
0 commit comments