Reputation: 9
I have a struct that represent a Vault. I'm trying test a scenario where a Player cannot retrieve a item that not exist in vault. The follow code represents this scenario.
vault.go
package vault
type Vault struct {
valueobjects.VaultID
Items []*item.Item
GoldAmount int
sync.Mutex
}
func NewVault() *Vault {
vault := Vault{
VaultID: valueobjects.NewVaultID(uuid.New()),
Items: []*item.Item{},
GoldAmount: 0,
}
return &vault
}
func (v *Vault) AddItem(i *item.Item, p *player.Player) error {
v.Lock()
defer v.Unlock()
err := p.RetriveItem(i)
if err != nil {
return NewVaultError(ErrInvalidOperation, err)
}
v.Items = append(v.Items, i)
return nil
}
func (v *Vault) RetriveItem(i *item.Item, p *player.Player) error {
v.Lock()
defer v.Unlock()
if len(v.Items) == 0 {
return NewVaultError(ErrEmptyVault, nil)
}
for index, item := range v.Items {
if item.ID() == i.ID() {
if err := p.PickItem(i); err != nil {
return NewVaultError(ErrInvalidOperation, err)
}
v.Items = append(v.Items[:index], v.Items[index+1:]...)
return nil
}
}
return NewVaultError(ErrItemNotFound, nil)
}
vault_test.go
package vault
var (
vaultInstance *Vault
vaultOnce sync.Once
)
func TestInicializeVault(t *testing.T) {
t.Cleanup(resetVault)
vault := getVault()
if vault == nil {
t.Error("Error initializing vault")
return
}
t.Run("Check initial vault gold amount", func(t *testing.T) {
assert.Equal(t, 0, vault.GoldAmount)
})
t.Run("Check initial items stored", func(t *testing.T) {
assert.Equal(t, 0, len(vault.Items))
})
}
func TestVaultID(t *testing.T) {
vault := NewVault()
if vault == nil {
t.Error("Error initializing vault")
return
}
t.Run("Check vault ID", func(t *testing.T) {
assert.NotEqual(t, "", vault.ID())
})
}
func TestRetriveItem(t *testing.T) {
t.Cleanup(resetVault)
vault := NewVault()
regPlayer, _ := player.NewPlayer("RegularPlayer", common.Ranger)
maxInvPlayer, _ := player.NewPlayer("MaxInvPlayer", common.Warrior)
item1 := item.PickRandomItem()
item2 := item.PickRandomItem()
fillPlayerInventory(regPlayer, item1, 2)
fillPlayerInventory(maxInvPlayer, item2, 10)
if vault == nil {
t.Error("Error initializing vault")
return
}
t.Run("Retrieve unexisting item from vault", func(t *testing.T) {
var vaultError *VaultError
vault.AddItem(item1, regPlayer)
err := vault.RetriveItem(item.PickRandomItem(), regPlayer)
assert.ErrorAs(t, err, &vaultError)
})
}
func fillPlayerInventory(p *player.Player, i *item.Item, t int) {
for j := 0; j <= t; j++ {
p.PickItem(i)
}
}
func resetVault() {
vaultInstance = NewVault()
}
func getVault() *Vault {
vaultOnce.Do(func() {
vaultInstance = NewVault()
})
return vaultInstance
}
No matter what I do, the parameter that is being passed to RetriveItem
is always item1.
I cant figure out what I'm doing wrong. I appreciate any help
I expect understand why my test doesn't work properly.
--- UPDATE with more definitions
item.go
package item
var (
ITEMS = []string{"Sword", "Shield", "Helmet", "Boots", "Gloves", "Potion", "Ring", "Amulet", "Scroll", "Book"}
)
type Item struct {
valueobjects.ItemID
name string
}
func PickRandomItem() *Item {
return initializeItem(ITEMS[rand.Intn(10)])
}
func (i *Item) Name() string {
return i.name
}
func initializeItem(name string) *Item {
return &Item{
name: name,
}
}
base_id.go
package common
type BaseID[T comparable] struct {
value T
}
func NewBaseID[T comparable](value T) BaseID[T] {
return BaseID[T]{value: value}
}
func (b BaseID[T]) ID() T {
return b.value
}
func (this BaseID[T]) Equals(object any) bool {
o, ok := object.(BaseID[T])
return ok && this.value == o.value
}
vault_id.go and others Id definition are pretty much the same.
package valueobjects
type VaultID struct {
common.BaseID[uuid.UUID]
}
func NewVaultID(value uuid.UUID) VaultID {
return VaultID{
BaseID: common.NewBaseID(value),
}
}
func (pID VaultID) Equals(otherID VaultID) bool {
return pID.BaseID.Equals(otherID.BaseID)
}
Upvotes: -4
Views: 54
Reputation: 9
I think I found the issue. I still investigating, but I notice that my function to initializa items wasn't define and ID for Items.
After this moditification on that struct:
func initializeItem(name string) *Item {
return &Item{
ItemID: valueobjects.NewItemID(uuid.New()),
name: name,
}
}
and change my tests a little bit:
t.Run("Retrieve unexisting item from vault", func(t *testing.T) {
var vaultErr *VaultError
vault.AddItem(item1, regPlayer)
vaultSize := len(vault.Items)
err := vault.RetriveItem(item.PickRandomItem(), regPlayer)
assert.Error(t, vault.RetriveItem(item3, regPlayer))
assert.ErrorAs(t, err, &vaultErr)
assert.Contains(t, vaultErr.Error(), ErrItemNotFound.Error())
assert.Equal(t, vaultSize, len(vault.Items))
})
It starting to working.
I need to do more investigation to understand this. But for now, it working!
Upvotes: 0