You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
352 lines
9.0 KiB
352 lines
9.0 KiB
package unit |
|
|
|
import ( |
|
"context" |
|
"errors" |
|
"testing" |
|
"time" |
|
|
|
"autostore/internal/application/commands" |
|
"autostore/internal/domain/entities" |
|
"autostore/internal/domain/specifications" |
|
) |
|
|
|
|
|
func createTestCommand() (*commands.AddItemCommand, *mockItemRepository, *mockOrderService, *mockTimeProvider, *mockLogger) { |
|
itemRepo := &mockItemRepository{} |
|
orderService := &mockOrderService{} |
|
timeProvider := &mockTimeProvider{ |
|
nowFunc: func() time.Time { |
|
t, _ := time.Parse(dateFormat, mockedNow) |
|
return t |
|
}, |
|
} |
|
expirationSpec := specifications.NewItemExpirationSpec() |
|
logger := &mockLogger{} |
|
|
|
cmd := commands.NewAddItemCommand(itemRepo, orderService, timeProvider, expirationSpec, logger) |
|
return cmd, itemRepo, orderService, timeProvider, logger |
|
} |
|
|
|
func TestWhenItemNotExpiredThenItemSaved(t *testing.T) { |
|
// Given |
|
cmd, itemRepo, _, _, _ := createTestCommand() |
|
|
|
expirationTime, _ := time.Parse(dateFormat, notExpiredDate) |
|
|
|
itemSaved := false |
|
itemRepo.saveFunc = func(ctx context.Context, item *entities.ItemEntity) error { |
|
itemSaved = true |
|
if item.GetName() != itemName { |
|
t.Errorf("Expected item name %s, got %s", itemName, item.GetName()) |
|
} |
|
if item.GetOrderURL() != orderURL { |
|
t.Errorf("Expected order URL %s, got %s", orderURL, item.GetOrderURL()) |
|
} |
|
if item.GetUserID().String() != userID { |
|
t.Errorf("Expected user ID %s, got %s", userID, item.GetUserID().String()) |
|
} |
|
return nil |
|
} |
|
|
|
// When |
|
resultID, err := cmd.Execute(context.Background(), itemName, expirationTime, orderURL, userID) |
|
|
|
// Then |
|
if err != nil { |
|
t.Errorf("Expected no error, got %v", err) |
|
} |
|
if resultID == "" { |
|
t.Error("Expected non-empty result ID") |
|
} |
|
if !itemSaved { |
|
t.Error("Expected item to be saved") |
|
} |
|
} |
|
|
|
func TestWhenItemNotExpiredThenOrderIsNotPlaced(t *testing.T) { |
|
// Given |
|
cmd, _, orderService, _, _ := createTestCommand() |
|
|
|
expirationTime, _ := time.Parse(dateFormat, notExpiredDate) |
|
|
|
orderPlaced := false |
|
orderService.orderItemFunc = func(ctx context.Context, item *entities.ItemEntity) error { |
|
orderPlaced = true |
|
return nil |
|
} |
|
|
|
// When |
|
_, err := cmd.Execute(context.Background(), itemName, expirationTime, orderURL, userID) |
|
|
|
// Then |
|
if err != nil { |
|
t.Errorf("Expected no error, got %v", err) |
|
} |
|
if orderPlaced { |
|
t.Error("Expected order not to be placed for non-expired item") |
|
} |
|
} |
|
|
|
func TestWhenItemNotExpiredThenNewItemIdIsReturned(t *testing.T) { |
|
// Given |
|
cmd, _, _, _, _ := createTestCommand() |
|
|
|
expirationTime, _ := time.Parse(dateFormat, notExpiredDate) |
|
|
|
// When |
|
resultID, err := cmd.Execute(context.Background(), itemName, expirationTime, orderURL, userID) |
|
|
|
// Then |
|
if err != nil { |
|
t.Errorf("Expected no error, got %v", err) |
|
} |
|
if resultID == "" { |
|
t.Error("Expected non-empty result ID") |
|
} |
|
} |
|
|
|
func TestWhenItemIsExpiredThenOrderPlaced(t *testing.T) { |
|
// Given |
|
cmd, itemRepo, orderService, timeProvider, _ := createTestCommand() |
|
|
|
// Set expiration time to 1 hour before current time to ensure it's expired |
|
currentTime := timeProvider.Now() |
|
expirationTime := currentTime.Add(-1 * time.Hour) |
|
|
|
orderPlaced := false |
|
var orderedItem *entities.ItemEntity |
|
|
|
itemRepo.saveFunc = func(ctx context.Context, item *entities.ItemEntity) error { |
|
return nil |
|
} |
|
|
|
orderService.orderItemFunc = func(ctx context.Context, item *entities.ItemEntity) error { |
|
orderPlaced = true |
|
orderedItem = item |
|
return nil |
|
} |
|
|
|
// When |
|
resultID, err := cmd.Execute(context.Background(), itemName, expirationTime, orderURL, userID) |
|
|
|
// Then |
|
if err != nil { |
|
t.Errorf("Expected no error, got %v", err) |
|
} |
|
if resultID == "" { |
|
t.Error("Expected non-empty result ID") |
|
} |
|
if !orderPlaced { |
|
t.Error("Expected order to be placed for expired item") |
|
} |
|
if orderedItem == nil { |
|
t.Error("Expected ordered item to be captured") |
|
} |
|
if orderedItem != nil && orderedItem.GetName() != itemName { |
|
t.Errorf("Expected ordered item name %s, got %s", itemName, orderedItem.GetName()) |
|
} |
|
} |
|
|
|
func TestWhenItemNameIsEmptyThenErrorReturned(t *testing.T) { |
|
// Given |
|
cmd, _, _, _, _ := createTestCommand() |
|
|
|
expirationTime, _ := time.Parse(dateFormat, notExpiredDate) |
|
|
|
// When |
|
_, err := cmd.Execute(context.Background(), "", expirationTime, orderURL, userID) |
|
|
|
// Then |
|
if err == nil { |
|
t.Error("Expected error for empty item name") |
|
} |
|
} |
|
|
|
func TestWhenOrderUrlIsEmptyThenErrorReturned(t *testing.T) { |
|
// Given |
|
cmd, _, _, _, _ := createTestCommand() |
|
|
|
expirationTime, _ := time.Parse(dateFormat, notExpiredDate) |
|
|
|
// When |
|
_, err := cmd.Execute(context.Background(), itemName, expirationTime, "", userID) |
|
|
|
// Then |
|
if err == nil { |
|
t.Error("Expected error for empty order URL") |
|
} |
|
} |
|
|
|
func TestWhenUserIdIsEmptyThenErrorReturned(t *testing.T) { |
|
// Given |
|
cmd, _, _, _, _ := createTestCommand() |
|
|
|
expirationTime, _ := time.Parse(dateFormat, notExpiredDate) |
|
|
|
// When |
|
_, err := cmd.Execute(context.Background(), itemName, expirationTime, orderURL, "") |
|
|
|
// Then |
|
if err == nil { |
|
t.Error("Expected error for empty user ID") |
|
} |
|
} |
|
|
|
func TestWhenOrderServiceFailsThenErrorLogged(t *testing.T) { |
|
// Given |
|
cmd, itemRepo, orderService, _, _ := createTestCommand() |
|
|
|
expirationTime, _ := time.Parse(dateFormat, expiredDate) |
|
|
|
itemRepo.saveFunc = func(ctx context.Context, item *entities.ItemEntity) error { |
|
return nil |
|
} |
|
|
|
orderService.orderItemFunc = func(ctx context.Context, item *entities.ItemEntity) error { |
|
return errors.New("order service failed") |
|
} |
|
|
|
// When - the handler should not throw an exception when the order service fails |
|
// It should log the error and continue |
|
resultID, err := cmd.Execute(context.Background(), itemName, expirationTime, orderURL, userID) |
|
|
|
// Then |
|
if err != nil { |
|
t.Errorf("Expected no error when order service fails, got %v", err) |
|
} |
|
if resultID == "" { |
|
t.Error("Expected non-empty result ID even when order service fails") |
|
} |
|
} |
|
|
|
func TestWhenRepositorySaveThrowsExceptionThenErrorReturned(t *testing.T) { |
|
// Given |
|
cmd, itemRepo, _, _, _ := createTestCommand() |
|
|
|
expirationTime, _ := time.Parse(dateFormat, notExpiredDate) |
|
|
|
expectedError := errors.New("repository error") |
|
itemRepo.saveFunc = func(ctx context.Context, item *entities.ItemEntity) error { |
|
return expectedError |
|
} |
|
|
|
// When |
|
_, err := cmd.Execute(context.Background(), itemName, expirationTime, orderURL, userID) |
|
|
|
// Then |
|
if err == nil { |
|
t.Error("Expected error when repository save fails") |
|
} |
|
} |
|
|
|
func TestWhenRepositorySaveThrowsExceptionThenOrderIsNotPlaced(t *testing.T) { |
|
// Given |
|
cmd, itemRepo, orderService, _, _ := createTestCommand() |
|
|
|
expirationTime, _ := time.Parse(dateFormat, expiredDate) |
|
|
|
expectedError := errors.New("repository error") |
|
itemRepo.saveFunc = func(ctx context.Context, item *entities.ItemEntity) error { |
|
return expectedError |
|
} |
|
|
|
orderPlaced := false |
|
orderService.orderItemFunc = func(ctx context.Context, item *entities.ItemEntity) error { |
|
orderPlaced = true |
|
return nil |
|
} |
|
|
|
// When |
|
_, err := cmd.Execute(context.Background(), itemName, expirationTime, orderURL, userID) |
|
|
|
// Then |
|
if err == nil { |
|
t.Error("Expected error when repository save fails") |
|
} |
|
if orderPlaced { |
|
t.Error("Expected order not to be placed when repository save fails") |
|
} |
|
} |
|
|
|
func TestWhenTimeProviderThrowsExceptionThenErrorReturned(t *testing.T) { |
|
// Given |
|
cmd, _, _, timeProvider, _ := createTestCommand() |
|
|
|
expirationTime, _ := time.Parse(dateFormat, notExpiredDate) |
|
|
|
expectedError := errors.New("time provider error") |
|
timeProvider.nowFunc = func() time.Time { |
|
panic(expectedError) |
|
} |
|
|
|
// When |
|
defer func() { |
|
if r := recover(); r != nil { |
|
// Expected panic |
|
} else { |
|
t.Error("Expected panic when time provider fails") |
|
} |
|
}() |
|
|
|
cmd.Execute(context.Background(), itemName, expirationTime, orderURL, userID) |
|
} |
|
|
|
func TestWhenItemExpirationDateIsExactlyCurrentTimeThenOrderIsPlaced(t *testing.T) { |
|
// Given |
|
cmd, itemRepo, orderService, timeProvider, _ := createTestCommand() |
|
|
|
// Use the exact current time from the time provider |
|
currentTime := timeProvider.Now() |
|
|
|
orderPlaced := false |
|
itemRepo.saveFunc = func(ctx context.Context, item *entities.ItemEntity) error { |
|
return nil |
|
} |
|
|
|
orderService.orderItemFunc = func(ctx context.Context, item *entities.ItemEntity) error { |
|
orderPlaced = true |
|
return nil |
|
} |
|
|
|
// When |
|
resultID, err := cmd.Execute(context.Background(), itemName, currentTime, orderURL, userID) |
|
|
|
// Then |
|
if err != nil { |
|
t.Errorf("Expected no error, got %v", err) |
|
} |
|
if resultID == "" { |
|
t.Error("Expected non-empty result ID") |
|
} |
|
if !orderPlaced { |
|
t.Error("Expected order to be placed when expiration date equals current time") |
|
} |
|
} |
|
|
|
func TestWhenItemExpirationDateIsInFutureThenItemSaved(t *testing.T) { |
|
// Given |
|
cmd, itemRepo, _, _, _ := createTestCommand() |
|
|
|
expirationTime, _ := time.Parse(dateFormat, notExpiredDate) |
|
|
|
itemSaved := false |
|
itemRepo.saveFunc = func(ctx context.Context, item *entities.ItemEntity) error { |
|
itemSaved = true |
|
return nil |
|
} |
|
|
|
// When |
|
resultID, err := cmd.Execute(context.Background(), itemName, expirationTime, orderURL, userID) |
|
|
|
// Then |
|
if err != nil { |
|
t.Errorf("Expected no error, got %v", err) |
|
} |
|
if resultID == "" { |
|
t.Error("Expected non-empty result ID") |
|
} |
|
if !itemSaved { |
|
t.Error("Expected item to be saved when expiration date is in future") |
|
} |
|
} |