Multiple implementations of the same back-end application. The aim is to provide quick, side-by-side comparisons of different technologies (languages, frameworks, libraries) while preserving consistent business logic across all implementations.
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

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))
}
}