Skip to content

Commit cb933c7

Browse files
shelly-li-slHarshit-Khasnis
authored andcommitted
Add update has one tests (#18)
* add update has one tests
1 parent 0d99973 commit cb933c7

File tree

1 file changed

+280
-0
lines changed

1 file changed

+280
-0
lines changed

tests/update_has_one_test.go

Lines changed: 280 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,15 @@ package tests
4040

4141
import (
4242
"database/sql"
43+
"errors"
4344
"testing"
4445

4546
"time"
4647

4748
. "github.com/oracle-samples/gorm-oracle/tests/utils"
4849

4950
"gorm.io/gorm"
51+
"gorm.io/gorm/clause"
5052
"gorm.io/gorm/utils/tests"
5153
)
5254

@@ -128,6 +130,87 @@ func TestUpdateHasOne(t *testing.T) {
128130
CheckPetSkipUpdatedAt(t, pet4, pet)
129131
})
130132

133+
t.Run("ReplaceAssociation", func(t *testing.T) {
134+
user := *GetUser("replace-has-one", Config{})
135+
136+
if err := DB.Create(&user).Error; err != nil {
137+
t.Fatalf("errors happened when create user: %v", err)
138+
}
139+
140+
acc1 := Account{AccountNumber: "first-account"}
141+
user.Account = acc1
142+
143+
if err := DB.Save(&user).Error; err != nil {
144+
t.Fatalf("errors happened when saving user with first account: %v", err)
145+
}
146+
147+
acc2 := Account{AccountNumber: "second-account"}
148+
user.Account = acc2
149+
if err := DB.Session(&gorm.Session{FullSaveAssociations: true}).Save(&user).Error; err != nil {
150+
t.Fatalf("errors happened when replacing association: %v", err)
151+
}
152+
153+
var result User
154+
DB.Preload("Account").First(&result, user.ID)
155+
if result.Account.AccountNumber != "second-account" {
156+
t.Fatalf("expected replaced account to have AccountNumber 'second-account', got %v", result.Account.AccountNumber)
157+
}
158+
})
159+
160+
t.Run("ClearHasOneAssociation", func(t *testing.T) {
161+
user := *GetUser("nullify-has-one", Config{})
162+
163+
if err := DB.Create(&user).Error; err != nil {
164+
t.Fatalf("errors happened when create user: %v", err)
165+
}
166+
167+
user.Account = Account{AccountNumber: "to-be-nullified"}
168+
if err := DB.Save(&user).Error; err != nil {
169+
t.Fatalf("errors happened when saving user: %v", err)
170+
}
171+
172+
DB.Model(&user).Association("Account").Clear()
173+
174+
var result User
175+
DB.Preload("Account").First(&result, user.ID)
176+
if result.Account.AccountNumber != "" {
177+
t.Fatalf("expected account to be nullified/empty, got %v", result.Account.AccountNumber)
178+
}
179+
})
180+
181+
t.Run("ClearPolymorphicAssociation", func(t *testing.T) {
182+
pet := Pet{Name: "clear-poly"}
183+
pet.Toy = Toy{Name: "polytoy"}
184+
DB.Create(&pet)
185+
186+
DB.Model(&pet).Association("Toy").Clear()
187+
188+
var pet2 Pet
189+
DB.Preload("Toy").First(&pet2, pet.ID)
190+
if pet2.Toy.Name != "" {
191+
t.Fatalf("expected Toy cleared, got %v", pet2.Toy.Name)
192+
}
193+
})
194+
195+
t.Run("UpdateWithoutAssociation", func(t *testing.T) {
196+
user := *GetUser("no-assoc-update", Config{})
197+
if err := DB.Create(&user).Error; err != nil {
198+
t.Fatalf("errors happened when create user: %v", err)
199+
}
200+
newName := user.Name + "-updated"
201+
if err := DB.Model(&user).Update("name", newName).Error; err != nil {
202+
t.Fatalf("errors happened when updating only parent: %v", err)
203+
}
204+
var result User
205+
DB.Preload("Account").First(&result, user.ID)
206+
if result.Name != newName {
207+
t.Fatalf("user name not updated as expected")
208+
}
209+
if result.Account.ID != 0 {
210+
t.Fatalf("expected no Account associated, got ID %v", result.Account.ID)
211+
}
212+
})
213+
131214
t.Run("Restriction", func(t *testing.T) {
132215
type CustomizeAccount struct {
133216
gorm.Model
@@ -175,4 +258,201 @@ func TestUpdateHasOne(t *testing.T) {
175258
tests.AssertEqual(t, account2.Number, number)
176259
tests.AssertEqual(t, account2.Number2, cusUser.Account.Number2)
177260
})
261+
262+
t.Run("AssociationWithoutPreload", func(t *testing.T) {
263+
user := *GetUser("no-preload", Config{})
264+
user.Account = Account{AccountNumber: "np-account"}
265+
DB.Create(&user)
266+
267+
var result User
268+
DB.First(&result, user.ID) // no preload
269+
if result.Account.AccountNumber != "" {
270+
t.Fatalf("expected Account field empty without preload, got %v", result.Account.AccountNumber)
271+
}
272+
273+
var acc Account
274+
DB.First(&acc, "\"user_id\" = ?", user.ID)
275+
if acc.AccountNumber != "np-account" {
276+
t.Fatalf("account not found as expected")
277+
}
278+
})
279+
280+
t.Run("SkipFullSaveAssociations", func(t *testing.T) {
281+
user := *GetUser("skip-fsa", Config{})
282+
user.Account = Account{AccountNumber: "skipfsa"}
283+
DB.Create(&user)
284+
285+
user.Account.AccountNumber = "should-not-update"
286+
if err := DB.Session(&gorm.Session{FullSaveAssociations: false}).Save(&user).Error; err != nil {
287+
t.Fatalf("error saving with FSA false: %v", err)
288+
}
289+
290+
var acc Account
291+
DB.First(&acc, "\"user_id\" = ?", user.ID)
292+
if acc.AccountNumber != "skipfsa" {
293+
t.Fatalf("account should not have updated, got %v", acc.AccountNumber)
294+
}
295+
})
296+
297+
t.Run("HasOneZeroForeignKey", func(t *testing.T) {
298+
now := time.Now()
299+
user := User{Name: "zero-value-clear", Age: 18, Birthday: &now}
300+
DB.Create(&user)
301+
302+
account := Account{AccountNumber: "to-clear", UserID: sql.NullInt64{Int64: int64(user.ID), Valid: true}}
303+
DB.Create(&account)
304+
305+
account.UserID = sql.NullInt64{Int64: 0, Valid: false}
306+
DB.Model(&account).Select("UserID").Updates(account)
307+
308+
var result User
309+
DB.Preload("Account").First(&result, user.ID)
310+
if result.Account.AccountNumber != "" {
311+
t.Fatalf("expected account cleared, got %v", result.Account.AccountNumber)
312+
}
313+
})
314+
315+
t.Run("PolymorphicZeroForeignKey", func(t *testing.T) {
316+
pet := Pet{Name: "poly-zero"}
317+
pet.Toy = Toy{Name: "polytoy-zero"}
318+
DB.Create(&pet)
319+
320+
pet.Toy.OwnerID = ""
321+
DB.Model(&pet.Toy).Select("OwnerID").Updates(&pet.Toy)
322+
323+
var pet2 Pet
324+
DB.Preload("Toy").First(&pet2, pet.ID)
325+
if pet2.Toy.Name != "" {
326+
t.Fatalf("expected polymorphic association cleared, got %v", pet2.Toy.Name)
327+
}
328+
})
329+
330+
t.Run("InvalidForeignKey", func(t *testing.T) {
331+
acc := Account{AccountNumber: "badfk", UserID: sql.NullInt64{Int64: 99999999, Valid: true}}
332+
err := DB.Create(&acc).Error
333+
if err == nil {
334+
t.Fatalf("expected foreign key constraint error, got nil")
335+
}
336+
})
337+
338+
t.Run("UpdateWithSelectOmit", func(t *testing.T) {
339+
user := *GetUser("select-omit", Config{})
340+
user.Account = Account{AccountNumber: "selomit"}
341+
DB.Create(&user)
342+
343+
user.Name = "selomit-updated"
344+
user.Account.AccountNumber = "selomit-updated"
345+
if err := DB.Select("Name").Omit("Account").Save(&user).Error; err != nil {
346+
t.Fatalf("error on select/omit: %v", err)
347+
}
348+
349+
var acc Account
350+
DB.First(&acc, "\"user_id\" = ?", user.ID)
351+
if acc.AccountNumber != "selomit" {
352+
t.Fatalf("account should not update with Omit(Account), got %v", acc.AccountNumber)
353+
}
354+
})
355+
356+
t.Run("NestedUpdate", func(t *testing.T) {
357+
user := *GetUser("nested-update", Config{})
358+
user.Account = Account{AccountNumber: "nested"}
359+
DB.Create(&user)
360+
361+
user.Name = "nested-updated"
362+
user.Account.AccountNumber = "nested-updated"
363+
if err := DB.Session(&gorm.Session{FullSaveAssociations: true}).Updates(&user).Error; err != nil {
364+
t.Fatalf("nested update failed: %v", err)
365+
}
366+
367+
var result User
368+
DB.Preload("Account").First(&result, user.ID)
369+
if result.Name != "nested-updated" || result.Account.AccountNumber != "nested-updated" {
370+
t.Fatalf("nested update didn't apply: %v / %v", result.Name, result.Account.AccountNumber)
371+
}
372+
})
373+
374+
t.Run("EmptyStructNoFullSave", func(t *testing.T) {
375+
user := *GetUser("empty-nofsa", Config{})
376+
user.Account = Account{AccountNumber: "keep"}
377+
DB.Create(&user)
378+
379+
user.Account = Account{}
380+
if err := DB.Save(&user).Error; err != nil {
381+
t.Fatalf("save failed: %v", err)
382+
}
383+
384+
var result User
385+
DB.Preload("Account").First(&result, user.ID)
386+
if result.Account.AccountNumber != "keep" {
387+
t.Fatalf("account should not be cleared without FullSaveAssociations")
388+
}
389+
})
390+
391+
t.Run("DeleteParentCascade", func(t *testing.T) {
392+
type AccountCascadeDelete struct {
393+
gorm.Model
394+
AccountNumber string
395+
UserID uint
396+
}
397+
398+
type UserCascadeDelete struct {
399+
gorm.Model
400+
Name string
401+
Account AccountCascadeDelete `gorm:"foreignKey:UserID;constraint:OnDelete:CASCADE;"`
402+
}
403+
404+
DB.Migrator().DropTable(&AccountCascadeDelete{}, &UserCascadeDelete{})
405+
if err := DB.AutoMigrate(&UserCascadeDelete{}, &AccountCascadeDelete{}); err != nil {
406+
t.Fatalf("failed to migrate: %v", err)
407+
}
408+
409+
user := UserCascadeDelete{
410+
Name: "delete-parent",
411+
Account: AccountCascadeDelete{
412+
AccountNumber: "cascade",
413+
},
414+
}
415+
416+
if err := DB.Create(&user).Error; err != nil {
417+
t.Fatalf("failed to create user: %v", err)
418+
}
419+
420+
if err := DB.Unscoped().Delete(&user).Error; err != nil {
421+
t.Fatalf("delete parent failed: %v", err)
422+
}
423+
424+
var acc AccountCascadeDelete
425+
err := DB.First(&acc, "\"user_id\" = ?", user.ID).Error
426+
if !errors.Is(err, gorm.ErrRecordNotFound) {
427+
t.Fatalf("expected account deleted, got %v", acc)
428+
}
429+
})
430+
431+
t.Run("OmitAllAssociations", func(t *testing.T) {
432+
user := *GetUser("omit-assoc", Config{})
433+
user.Account = Account{AccountNumber: "original-child"}
434+
if err := DB.Create(&user).Error; err != nil {
435+
t.Fatalf("failed to create user: %v", err)
436+
}
437+
438+
newName := "parent-updated"
439+
user.Name = newName
440+
user.Account.AccountNumber = "child-updated"
441+
442+
if err := DB.Model(&user).Omit(clause.Associations).Updates(user).Error; err != nil {
443+
t.Fatalf("update with omit associations failed: %v", err)
444+
}
445+
446+
var result User
447+
DB.Preload("Account").First(&result, user.ID)
448+
449+
if result.Name != newName {
450+
t.Fatalf("expected parent name updated to %v, got %v", newName, result.Name)
451+
}
452+
453+
if result.Account.AccountNumber != "original-child" {
454+
t.Fatalf("expected child to remain unchanged, got %v", result.Account.AccountNumber)
455+
}
456+
})
457+
178458
}

0 commit comments

Comments
 (0)