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.
293 lines
8.5 KiB
293 lines
8.5 KiB
package unit |
|
|
|
import ( |
|
"context" |
|
"errors" |
|
"testing" |
|
"time" |
|
|
|
"autostore/internal/application/commands" |
|
"autostore/internal/domain/entities" |
|
"autostore/internal/domain/specifications" |
|
"autostore/internal/domain/value_objects" |
|
) |
|
|
|
func createExpiredItem1() *entities.ItemEntity { |
|
expirationTime, _ := time.Parse(dateFormat, expiredDate) |
|
itemID, _ := value_objects.NewItemIDFromString("550e8400-e29b-41d4-a716-446655440001") |
|
userID, _ := value_objects.NewUserIDFromString("550e8400-e29b-41d4-a716-446655440003") |
|
expirationDate, _ := value_objects.NewExpirationDate(expirationTime) |
|
|
|
item, _ := entities.NewItem(itemID, "Expired Item 1", expirationDate, "http://example.com/order1", userID) |
|
return item |
|
} |
|
|
|
func createExpiredItem2() *entities.ItemEntity { |
|
expirationTime, _ := time.Parse(dateFormat, expiredDate) |
|
itemID, _ := value_objects.NewItemIDFromString("550e8400-e29b-41d4-a716-446655440002") |
|
userID, _ := value_objects.NewUserIDFromString("550e8400-e29b-41d4-a716-446655440004") |
|
expirationDate, _ := value_objects.NewExpirationDate(expirationTime) |
|
|
|
item, _ := entities.NewItem(itemID, "Expired Item 2", expirationDate, "http://example.com/order2", userID) |
|
return item |
|
} |
|
|
|
func createTestHandleExpiredItemsCommand() (*commands.HandleExpiredItemsCommand, *mockItemRepository, *mockOrderService, *mockTimeProvider, *specifications.ItemExpirationSpec, *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.NewHandleExpiredItemsCommand(itemRepo, orderService, timeProvider, expirationSpec, logger) |
|
return cmd, itemRepo, orderService, timeProvider, expirationSpec, logger |
|
} |
|
|
|
func TestWhenNoExpiredItemsExistThenNoOrdersPlaced(t *testing.T) { |
|
// Given |
|
cmd, itemRepo, orderService, _, _, logger := createTestHandleExpiredItemsCommand() |
|
|
|
itemRepo.findWhereFunc = func(ctx context.Context, spec specifications.Specification[*entities.ItemEntity]) ([]*entities.ItemEntity, error) { |
|
return []*entities.ItemEntity{}, nil |
|
} |
|
|
|
orderCalled := false |
|
orderService.orderItemFunc = func(ctx context.Context, item *entities.ItemEntity) error { |
|
orderCalled = true |
|
return nil |
|
} |
|
|
|
deleteCalled := false |
|
itemRepo.deleteFunc = func(ctx context.Context, id value_objects.ItemID) error { |
|
deleteCalled = true |
|
return nil |
|
} |
|
|
|
// When |
|
err := cmd.Execute(context.Background()) |
|
|
|
// Then |
|
if err != nil { |
|
t.Errorf("Expected no error, got %v", err) |
|
} |
|
if orderCalled { |
|
t.Error("Expected order service not to be called") |
|
} |
|
if deleteCalled { |
|
t.Error("Expected delete not to be called") |
|
} |
|
if len(logger.errorLogs) > 0 { |
|
t.Error("Expected no error logs") |
|
} |
|
} |
|
|
|
func TestWhenExpiredItemsExistThenOrdersPlacedAndItemsDeleted(t *testing.T) { |
|
// Given |
|
cmd, itemRepo, orderService, _, _, logger := createTestHandleExpiredItemsCommand() |
|
|
|
expiredItem1 := createExpiredItem1() |
|
expiredItem2 := createExpiredItem2() |
|
expiredItems := []*entities.ItemEntity{expiredItem1, expiredItem2} |
|
|
|
itemRepo.findWhereFunc = func(ctx context.Context, spec specifications.Specification[*entities.ItemEntity]) ([]*entities.ItemEntity, error) { |
|
return expiredItems, nil |
|
} |
|
|
|
orderCallCount := 0 |
|
orderService.orderItemFunc = func(ctx context.Context, item *entities.ItemEntity) error { |
|
orderCallCount++ |
|
return nil |
|
} |
|
|
|
deleteCallCount := 0 |
|
itemRepo.deleteFunc = func(ctx context.Context, id value_objects.ItemID) error { |
|
deleteCallCount++ |
|
return nil |
|
} |
|
|
|
// When |
|
err := cmd.Execute(context.Background()) |
|
|
|
// Then |
|
if err != nil { |
|
t.Errorf("Expected no error, got %v", err) |
|
} |
|
if orderCallCount != 2 { |
|
t.Errorf("Expected order service to be called 2 times, got %d", orderCallCount) |
|
} |
|
if deleteCallCount != 2 { |
|
t.Errorf("Expected delete to be called 2 times, got %d", deleteCallCount) |
|
} |
|
if len(logger.errorLogs) > 0 { |
|
t.Error("Expected no error logs") |
|
} |
|
} |
|
|
|
func TestWhenOrderServiceFailsForOneItemThenErrorLoggedAndOtherItemProcessed(t *testing.T) { |
|
// Given |
|
cmd, itemRepo, orderService, _, _, logger := createTestHandleExpiredItemsCommand() |
|
|
|
expiredItem1 := createExpiredItem1() |
|
expiredItem2 := createExpiredItem2() |
|
expiredItems := []*entities.ItemEntity{expiredItem1, expiredItem2} |
|
|
|
itemRepo.findWhereFunc = func(ctx context.Context, spec specifications.Specification[*entities.ItemEntity]) ([]*entities.ItemEntity, error) { |
|
return expiredItems, nil |
|
} |
|
|
|
orderCallCount := 0 |
|
orderService.orderItemFunc = func(ctx context.Context, item *entities.ItemEntity) error { |
|
orderCallCount++ |
|
if orderCallCount == 1 { |
|
return errors.New("order service failed") |
|
} |
|
return nil |
|
} |
|
|
|
deleteCallCount := 0 |
|
itemRepo.deleteFunc = func(ctx context.Context, id value_objects.ItemID) error { |
|
deleteCallCount++ |
|
return nil |
|
} |
|
|
|
// When |
|
err := cmd.Execute(context.Background()) |
|
|
|
// Then |
|
if err != nil { |
|
t.Errorf("Expected no error, got %v", err) |
|
} |
|
if orderCallCount != 2 { |
|
t.Errorf("Expected order service to be called 2 times, got %d", orderCallCount) |
|
} |
|
if deleteCallCount != 1 { |
|
t.Errorf("Expected delete to be called 1 time (only for successful order), got %d", deleteCallCount) |
|
} |
|
if len(logger.errorLogs) != 1 { |
|
t.Errorf("Expected 1 error log, got %d", len(logger.errorLogs)) |
|
} |
|
} |
|
|
|
func TestWhenRepositoryFindThrowsErrorThenErrorReturned(t *testing.T) { |
|
// Given |
|
cmd, itemRepo, orderService, _, _, logger := createTestHandleExpiredItemsCommand() |
|
|
|
expectedError := errors.New("repository find error") |
|
itemRepo.findWhereFunc = func(ctx context.Context, spec specifications.Specification[*entities.ItemEntity]) ([]*entities.ItemEntity, error) { |
|
return nil, expectedError |
|
} |
|
|
|
orderCalled := false |
|
orderService.orderItemFunc = func(ctx context.Context, item *entities.ItemEntity) error { |
|
orderCalled = true |
|
return nil |
|
} |
|
|
|
// When |
|
err := cmd.Execute(context.Background()) |
|
|
|
// Then |
|
if err == nil { |
|
t.Error("Expected error, got nil") |
|
} |
|
if orderCalled { |
|
t.Error("Expected order service not to be called") |
|
} |
|
if len(logger.errorLogs) != 1 { |
|
t.Errorf("Expected 1 error log, got %d", len(logger.errorLogs)) |
|
} |
|
} |
|
|
|
func TestWhenRepositoryDeleteThrowsExceptionThenErrorLogged(t *testing.T) { |
|
// Given |
|
cmd, itemRepo, orderService, _, _, logger := createTestHandleExpiredItemsCommand() |
|
|
|
expiredItem1 := createExpiredItem1() |
|
expiredItems := []*entities.ItemEntity{expiredItem1} |
|
|
|
itemRepo.findWhereFunc = func(ctx context.Context, spec specifications.Specification[*entities.ItemEntity]) ([]*entities.ItemEntity, error) { |
|
return expiredItems, nil |
|
} |
|
|
|
orderService.orderItemFunc = func(ctx context.Context, item *entities.ItemEntity) error { |
|
return nil |
|
} |
|
|
|
expectedError := errors.New("delete failed") |
|
itemRepo.deleteFunc = func(ctx context.Context, id value_objects.ItemID) error { |
|
return expectedError |
|
} |
|
|
|
// When |
|
err := cmd.Execute(context.Background()) |
|
|
|
// Then |
|
if err == nil { |
|
t.Error("Expected error, got nil") |
|
} |
|
if len(logger.errorLogs) != 1 { |
|
t.Errorf("Expected 1 error log, got %d", len(logger.errorLogs)) |
|
} |
|
} |
|
|
|
func TestWhenTimeProviderThrowsErrorThenErrorReturned(t *testing.T) { |
|
// Given |
|
cmd, _, _, timeProvider, _, _ := createTestHandleExpiredItemsCommand() |
|
|
|
timeProvider.nowFunc = func() time.Time { |
|
panic("time provider error") |
|
} |
|
|
|
// When & Then |
|
defer func() { |
|
if r := recover(); r != nil { |
|
// Expected panic |
|
} else { |
|
t.Error("Expected panic when time provider fails") |
|
} |
|
}() |
|
|
|
cmd.Execute(context.Background()) |
|
} |
|
|
|
func TestWhenAllOrderServicesFailThenAllErrorsLogged(t *testing.T) { |
|
// Given |
|
cmd, itemRepo, orderService, _, _, logger := createTestHandleExpiredItemsCommand() |
|
|
|
expiredItem1 := createExpiredItem1() |
|
expiredItem2 := createExpiredItem2() |
|
expiredItems := []*entities.ItemEntity{expiredItem1, expiredItem2} |
|
|
|
itemRepo.findWhereFunc = func(ctx context.Context, spec specifications.Specification[*entities.ItemEntity]) ([]*entities.ItemEntity, error) { |
|
return expiredItems, nil |
|
} |
|
|
|
orderService.orderItemFunc = func(ctx context.Context, item *entities.ItemEntity) error { |
|
return errors.New("order service failed") |
|
} |
|
|
|
deleteCalled := false |
|
itemRepo.deleteFunc = func(ctx context.Context, id value_objects.ItemID) error { |
|
deleteCalled = true |
|
return nil |
|
} |
|
|
|
// When |
|
err := cmd.Execute(context.Background()) |
|
|
|
// Then |
|
if err != nil { |
|
t.Errorf("Expected no error, got %v", err) |
|
} |
|
if deleteCalled { |
|
t.Error("Expected delete not to be called when all orders fail") |
|
} |
|
if len(logger.errorLogs) != 2 { |
|
t.Errorf("Expected 2 error logs, got %d", len(logger.errorLogs)) |
|
} |
|
} |