github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/internal/domain/formationconstraint/service_test.go (about)

     1  package formationconstraint_test
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"reflect"
     7  	"testing"
     8  
     9  	"github.com/kyma-incubator/compass/components/director/internal/domain/formationconstraint"
    10  	"github.com/kyma-incubator/compass/components/director/internal/domain/formationconstraint/automock"
    11  	tnt "github.com/kyma-incubator/compass/components/director/internal/domain/tenant"
    12  	"github.com/kyma-incubator/compass/components/director/internal/model"
    13  	"github.com/stretchr/testify/assert"
    14  	"github.com/stretchr/testify/mock"
    15  	"github.com/stretchr/testify/require"
    16  )
    17  
    18  func TestService_Create(t *testing.T) {
    19  	// GIVEN
    20  	ctx := tnt.SaveToContext(context.TODO(), testTenantID, testTenantID)
    21  
    22  	testErr := errors.New("test error")
    23  
    24  	uidSvcFn := func() *automock.UidService {
    25  		uidSvc := &automock.UidService{}
    26  		uidSvc.On("Generate").Return(testID)
    27  		return uidSvc
    28  	}
    29  
    30  	testCases := []struct {
    31  		Name                          string
    32  		Context                       context.Context
    33  		Input                         *model.FormationConstraintInput
    34  		FormationConstraintRepository func() *automock.FormationConstraintRepository
    35  		FormationConstraintConverter  func() *automock.FormationConstraintConverter
    36  		ExpectedOutput                string
    37  		ExpectedError                 error
    38  	}{
    39  		{
    40  			Name:    "Success",
    41  			Context: ctx,
    42  			Input:   formationConstraintModelInput,
    43  			FormationConstraintConverter: func() *automock.FormationConstraintConverter {
    44  				converter := &automock.FormationConstraintConverter{}
    45  				converter.On("FromModelInputToModel", formationConstraintModelInput, testID).Return(formationConstraintModel).Once()
    46  				return converter
    47  			},
    48  			FormationConstraintRepository: func() *automock.FormationConstraintRepository {
    49  				repo := &automock.FormationConstraintRepository{}
    50  				repo.On("Create", ctx, formationConstraintModel).Return(nil).Once()
    51  				return repo
    52  			},
    53  			ExpectedOutput: testID,
    54  			ExpectedError:  nil,
    55  		},
    56  		{
    57  			Name:    "Error when creating formation constraint",
    58  			Context: ctx,
    59  			Input:   formationConstraintModelInput,
    60  			FormationConstraintConverter: func() *automock.FormationConstraintConverter {
    61  				converter := &automock.FormationConstraintConverter{}
    62  				converter.On("FromModelInputToModel", formationConstraintModelInput, testID).Return(formationConstraintModel).Once()
    63  				return converter
    64  			},
    65  			FormationConstraintRepository: func() *automock.FormationConstraintRepository {
    66  				repo := &automock.FormationConstraintRepository{}
    67  				repo.On("Create", ctx, formationConstraintModel).Return(testErr).Once()
    68  				return repo
    69  			},
    70  			ExpectedOutput: "",
    71  			ExpectedError:  testErr,
    72  		},
    73  	}
    74  
    75  	for _, testCase := range testCases {
    76  		t.Run(testCase.Name, func(t *testing.T) {
    77  			formationConstraintRepo := testCase.FormationConstraintRepository()
    78  			formationConstraintConv := testCase.FormationConstraintConverter()
    79  			idSvc := uidSvcFn()
    80  
    81  			svc := formationconstraint.NewService(formationConstraintRepo, nil, idSvc, formationConstraintConv)
    82  
    83  			// WHEN
    84  			result, err := svc.Create(testCase.Context, testCase.Input)
    85  
    86  			// THEN
    87  			if testCase.ExpectedError != nil {
    88  				require.Error(t, err)
    89  				assert.Contains(t, err.Error(), testCase.ExpectedError.Error())
    90  			} else {
    91  				assert.NoError(t, err)
    92  			}
    93  			assert.Equal(t, testCase.ExpectedOutput, result)
    94  
    95  			mock.AssertExpectationsForObjects(t, formationConstraintRepo, idSvc, formationConstraintConv)
    96  		})
    97  	}
    98  }
    99  
   100  func TestService_Get(t *testing.T) {
   101  	// GIVEN
   102  	ctx := context.TODO()
   103  
   104  	testErr := errors.New("test error")
   105  
   106  	testCases := []struct {
   107  		Name                          string
   108  		Input                         string
   109  		FormationConstraintRepository func() *automock.FormationConstraintRepository
   110  		ExpectedOutput                *model.FormationConstraint
   111  		ExpectedError                 error
   112  	}{
   113  		{
   114  			Name:  "Success",
   115  			Input: testID,
   116  			FormationConstraintRepository: func() *automock.FormationConstraintRepository {
   117  				repo := &automock.FormationConstraintRepository{}
   118  				repo.On("Get", ctx, testID).Return(formationConstraintModel, nil).Once()
   119  				return repo
   120  			},
   121  			ExpectedOutput: formationConstraintModel,
   122  			ExpectedError:  nil,
   123  		},
   124  		{
   125  			Name:  "Error when getting formation template",
   126  			Input: testID,
   127  			FormationConstraintRepository: func() *automock.FormationConstraintRepository {
   128  				repo := &automock.FormationConstraintRepository{}
   129  				repo.On("Get", ctx, testID).Return(nil, testErr).Once()
   130  				return repo
   131  			},
   132  			ExpectedOutput: nil,
   133  			ExpectedError:  testErr,
   134  		},
   135  	}
   136  
   137  	for _, testCase := range testCases {
   138  		t.Run(testCase.Name, func(t *testing.T) {
   139  			formationConstraintRepo := testCase.FormationConstraintRepository()
   140  
   141  			svc := formationconstraint.NewService(formationConstraintRepo, nil, nil, nil)
   142  
   143  			// WHEN
   144  			result, err := svc.Get(ctx, testCase.Input)
   145  
   146  			// THEN
   147  			if testCase.ExpectedError != nil {
   148  				require.Error(t, err)
   149  				assert.Contains(t, err.Error(), testCase.ExpectedError.Error())
   150  			} else {
   151  				assert.NoError(t, err)
   152  			}
   153  			assert.Equal(t, testCase.ExpectedOutput, result)
   154  
   155  			mock.AssertExpectationsForObjects(t, formationConstraintRepo)
   156  		})
   157  	}
   158  }
   159  
   160  func TestService_List(t *testing.T) {
   161  	// GIVEN
   162  	ctx := tnt.SaveToContext(context.TODO(), testTenantID, testTenantID)
   163  
   164  	testErr := errors.New("test error")
   165  
   166  	testCases := []struct {
   167  		Name                          string
   168  		Context                       context.Context
   169  		FormationConstraintRepository func() *automock.FormationConstraintRepository
   170  		ExpectedOutput                []*model.FormationConstraint
   171  		ExpectedError                 error
   172  	}{
   173  		{
   174  			Name:    "Success",
   175  			Context: ctx,
   176  			FormationConstraintRepository: func() *automock.FormationConstraintRepository {
   177  				repo := &automock.FormationConstraintRepository{}
   178  				repo.On("ListAll", ctx).Return([]*model.FormationConstraint{formationConstraintModel}, nil).Once()
   179  				return repo
   180  			},
   181  			ExpectedOutput: []*model.FormationConstraint{formationConstraintModel},
   182  			ExpectedError:  nil,
   183  		},
   184  		{
   185  			Name:    "Error when listing formation constraints",
   186  			Context: ctx,
   187  			FormationConstraintRepository: func() *automock.FormationConstraintRepository {
   188  				repo := &automock.FormationConstraintRepository{}
   189  				repo.On("ListAll", ctx).Return(nil, testErr).Once()
   190  				return repo
   191  			},
   192  			ExpectedOutput: nil,
   193  			ExpectedError:  testErr,
   194  		},
   195  	}
   196  
   197  	for _, testCase := range testCases {
   198  		t.Run(testCase.Name, func(t *testing.T) {
   199  			formationConstraintRepo := testCase.FormationConstraintRepository()
   200  
   201  			svc := formationconstraint.NewService(formationConstraintRepo, nil, nil, nil)
   202  
   203  			// WHEN
   204  			result, err := svc.List(testCase.Context)
   205  
   206  			// THEN
   207  			if testCase.ExpectedError != nil {
   208  				require.Error(t, err)
   209  				assert.Contains(t, err.Error(), testCase.ExpectedError.Error())
   210  			} else {
   211  				assert.NoError(t, err)
   212  			}
   213  			assert.Equal(t, testCase.ExpectedOutput, result)
   214  
   215  			mock.AssertExpectationsForObjects(t, formationConstraintRepo)
   216  		})
   217  	}
   218  }
   219  
   220  func TestService_ListByFormationTemplateID(t *testing.T) {
   221  	// GIVEN
   222  	ctx := tnt.SaveToContext(context.TODO(), testTenantID, testTenantID)
   223  
   224  	testErr := errors.New("test error")
   225  
   226  	testCases := []struct {
   227  		Name                                   string
   228  		Context                                context.Context
   229  		FormationConstraintRepository          func() *automock.FormationConstraintRepository
   230  		FormationConstraintReferenceRepository func() *automock.FormationTemplateConstraintReferenceRepository
   231  		ExpectedOutput                         []*model.FormationConstraint
   232  		ExpectedError                          error
   233  	}{
   234  		{
   235  			Name:    "Success",
   236  			Context: ctx,
   237  			FormationConstraintRepository: func() *automock.FormationConstraintRepository {
   238  				repo := &automock.FormationConstraintRepository{}
   239  				repo.On("ListByIDs", ctx, []string{testID}).Return([]*model.FormationConstraint{formationConstraintModel}, nil).Once()
   240  				return repo
   241  			},
   242  			FormationConstraintReferenceRepository: func() *automock.FormationTemplateConstraintReferenceRepository {
   243  				repo := &automock.FormationTemplateConstraintReferenceRepository{}
   244  				repo.On("ListByFormationTemplateID", ctx, formationTemplateID).Return([]*model.FormationTemplateConstraintReference{formationConstraintReference}, nil).Once()
   245  				return repo
   246  			},
   247  			ExpectedOutput: []*model.FormationConstraint{formationConstraintModel},
   248  			ExpectedError:  nil,
   249  		},
   250  		{
   251  			Name:    "Error when listing formation constraints",
   252  			Context: ctx,
   253  			FormationConstraintRepository: func() *automock.FormationConstraintRepository {
   254  				repo := &automock.FormationConstraintRepository{}
   255  				repo.On("ListByIDs", ctx, []string{testID}).Return(nil, testErr).Once()
   256  				return repo
   257  			},
   258  			FormationConstraintReferenceRepository: func() *automock.FormationTemplateConstraintReferenceRepository {
   259  				repo := &automock.FormationTemplateConstraintReferenceRepository{}
   260  				repo.On("ListByFormationTemplateID", ctx, formationTemplateID).Return([]*model.FormationTemplateConstraintReference{formationConstraintReference}, nil).Once()
   261  				return repo
   262  			},
   263  			ExpectedOutput: nil,
   264  			ExpectedError:  testErr,
   265  		},
   266  		{
   267  			Name:                          "Error when listing constraint references",
   268  			Context:                       ctx,
   269  			FormationConstraintRepository: UnusedFormationConstraintRepository,
   270  			FormationConstraintReferenceRepository: func() *automock.FormationTemplateConstraintReferenceRepository {
   271  				repo := &automock.FormationTemplateConstraintReferenceRepository{}
   272  				repo.On("ListByFormationTemplateID", ctx, formationTemplateID).Return(nil, testErr).Once()
   273  				return repo
   274  			},
   275  			ExpectedOutput: nil,
   276  			ExpectedError:  testErr,
   277  		},
   278  	}
   279  
   280  	for _, testCase := range testCases {
   281  		t.Run(testCase.Name, func(t *testing.T) {
   282  			formationConstraintRepo := testCase.FormationConstraintRepository()
   283  			formationConstraintReferenceRepo := testCase.FormationConstraintReferenceRepository()
   284  			svc := formationconstraint.NewService(formationConstraintRepo, formationConstraintReferenceRepo, nil, nil)
   285  
   286  			// WHEN
   287  			result, err := svc.ListByFormationTemplateID(testCase.Context, formationTemplateID)
   288  
   289  			// THEN
   290  			if testCase.ExpectedError != nil {
   291  				require.Error(t, err)
   292  				assert.Contains(t, err.Error(), testCase.ExpectedError.Error())
   293  			} else {
   294  				assert.NoError(t, err)
   295  			}
   296  			assert.Equal(t, testCase.ExpectedOutput, result)
   297  
   298  			mock.AssertExpectationsForObjects(t, formationConstraintRepo, formationConstraintReferenceRepo)
   299  		})
   300  	}
   301  }
   302  
   303  func TestService_Delete(t *testing.T) {
   304  	// GIVEN
   305  	ctx := tnt.SaveToContext(context.TODO(), testTenantID, testTenantID)
   306  	testErr := errors.New("test error")
   307  
   308  	testCases := []struct {
   309  		Name                          string
   310  		Context                       context.Context
   311  		Input                         string
   312  		FormationConstraintRepository func() *automock.FormationConstraintRepository
   313  		ExpectedError                 error
   314  	}{
   315  		{
   316  			Name:    "Success",
   317  			Context: ctx,
   318  			Input:   testID,
   319  			FormationConstraintRepository: func() *automock.FormationConstraintRepository {
   320  				repo := &automock.FormationConstraintRepository{}
   321  				repo.On("Delete", ctx, testID).Return(nil).Once()
   322  				return repo
   323  			},
   324  			ExpectedError: nil,
   325  		},
   326  		{
   327  			Name:    "Error when deleting formation constraint",
   328  			Context: ctx,
   329  			Input:   testID,
   330  			FormationConstraintRepository: func() *automock.FormationConstraintRepository {
   331  				repo := &automock.FormationConstraintRepository{}
   332  				repo.On("Delete", ctx, testID).Return(testErr).Once()
   333  				return repo
   334  			},
   335  			ExpectedError: testErr,
   336  		},
   337  	}
   338  
   339  	for _, testCase := range testCases {
   340  		t.Run(testCase.Name, func(t *testing.T) {
   341  			formationConstraintRepo := testCase.FormationConstraintRepository()
   342  
   343  			svc := formationconstraint.NewService(formationConstraintRepo, nil, nil, nil)
   344  
   345  			// WHEN
   346  			err := svc.Delete(testCase.Context, testCase.Input)
   347  
   348  			// THEN
   349  			if testCase.ExpectedError != nil {
   350  				require.Error(t, err)
   351  				assert.Contains(t, err.Error(), testCase.ExpectedError.Error())
   352  			} else {
   353  				assert.NoError(t, err)
   354  			}
   355  
   356  			mock.AssertExpectationsForObjects(t, formationConstraintRepo)
   357  		})
   358  	}
   359  }
   360  
   361  func TestService_ListMatchingConstraints(t *testing.T) {
   362  	// GIVEN
   363  	ctx := tnt.SaveToContext(context.TODO(), testTenantID, testTenantID)
   364  
   365  	testErr := errors.New("test error")
   366  
   367  	testCases := []struct {
   368  		Name                                   string
   369  		Context                                context.Context
   370  		FormationConstraintRepository          func() *automock.FormationConstraintRepository
   371  		FormationConstraintReferenceRepository func() *automock.FormationTemplateConstraintReferenceRepository
   372  		ExpectedOutput                         []*model.FormationConstraint
   373  		ExpectedError                          error
   374  	}{
   375  		{
   376  			Name:    "Success",
   377  			Context: ctx,
   378  			FormationConstraintRepository: func() *automock.FormationConstraintRepository {
   379  				repo := &automock.FormationConstraintRepository{}
   380  				repo.On("ListMatchingFormationConstraints", ctx, []string{testID}, location, matchingDetails).Return([]*model.FormationConstraint{formationConstraintModel}, nil).Once()
   381  				return repo
   382  			},
   383  			FormationConstraintReferenceRepository: func() *automock.FormationTemplateConstraintReferenceRepository {
   384  				repo := &automock.FormationTemplateConstraintReferenceRepository{}
   385  				repo.On("ListByFormationTemplateID", ctx, formationTemplateID).Return([]*model.FormationTemplateConstraintReference{formationConstraintReference}, nil).Once()
   386  				return repo
   387  			},
   388  			ExpectedOutput: []*model.FormationConstraint{formationConstraintModel},
   389  			ExpectedError:  nil,
   390  		},
   391  		{
   392  			Name:    "Error when listing formation constraints",
   393  			Context: ctx,
   394  			FormationConstraintRepository: func() *automock.FormationConstraintRepository {
   395  				repo := &automock.FormationConstraintRepository{}
   396  				repo.On("ListMatchingFormationConstraints", ctx, []string{testID}, location, matchingDetails).Return(nil, testErr).Once()
   397  				return repo
   398  			},
   399  			FormationConstraintReferenceRepository: func() *automock.FormationTemplateConstraintReferenceRepository {
   400  				repo := &automock.FormationTemplateConstraintReferenceRepository{}
   401  				repo.On("ListByFormationTemplateID", ctx, formationTemplateID).Return([]*model.FormationTemplateConstraintReference{formationConstraintReference}, nil).Once()
   402  				return repo
   403  			},
   404  			ExpectedOutput: nil,
   405  			ExpectedError:  testErr,
   406  		},
   407  		{
   408  			Name:                          "Error when listing constraint references",
   409  			Context:                       ctx,
   410  			FormationConstraintRepository: UnusedFormationConstraintRepository,
   411  			FormationConstraintReferenceRepository: func() *automock.FormationTemplateConstraintReferenceRepository {
   412  				repo := &automock.FormationTemplateConstraintReferenceRepository{}
   413  				repo.On("ListByFormationTemplateID", ctx, formationTemplateID).Return(nil, testErr).Once()
   414  				return repo
   415  			},
   416  			ExpectedOutput: nil,
   417  			ExpectedError:  testErr,
   418  		},
   419  	}
   420  
   421  	for _, testCase := range testCases {
   422  		t.Run(testCase.Name, func(t *testing.T) {
   423  			formationConstraintRepo := testCase.FormationConstraintRepository()
   424  			formationConstraintReferenceRepo := testCase.FormationConstraintReferenceRepository()
   425  			svc := formationconstraint.NewService(formationConstraintRepo, formationConstraintReferenceRepo, nil, nil)
   426  
   427  			// WHEN
   428  			result, err := svc.ListMatchingConstraints(testCase.Context, formationTemplateID, location, matchingDetails)
   429  
   430  			// THEN
   431  			if testCase.ExpectedError != nil {
   432  				require.Error(t, err)
   433  				assert.Contains(t, err.Error(), testCase.ExpectedError.Error())
   434  			} else {
   435  				assert.NoError(t, err)
   436  			}
   437  			assert.Equal(t, testCase.ExpectedOutput, result)
   438  
   439  			mock.AssertExpectationsForObjects(t, formationConstraintRepo, formationConstraintReferenceRepo)
   440  		})
   441  	}
   442  }
   443  
   444  func TestService_Update(t *testing.T) {
   445  	// GIVEN
   446  	ctx := context.TODO()
   447  
   448  	testErr := errors.New("test error")
   449  
   450  	testCases := []struct {
   451  		Name                          string
   452  		Context                       context.Context
   453  		InputConstraintTemplate       *model.FormationConstraintInput
   454  		FormationConstraintRepository func() *automock.FormationConstraintRepository
   455  		FormationConstraintConverter  func() *automock.FormationConstraintConverter
   456  		ExpectedErrorMessage          string
   457  	}{
   458  		{
   459  			Name:                    "Success",
   460  			Context:                 ctx,
   461  			InputConstraintTemplate: formationConstraintModelInput,
   462  			FormationConstraintRepository: func() *automock.FormationConstraintRepository {
   463  				repo := &automock.FormationConstraintRepository{}
   464  				repo.On("Update", ctx, formationConstraintModel).Return(nil).Once()
   465  				return repo
   466  			},
   467  			FormationConstraintConverter: func() *automock.FormationConstraintConverter {
   468  				converter := &automock.FormationConstraintConverter{}
   469  				converter.On("FromModelInputToModel", formationConstraintModelInput, testID).Return(formationConstraintModel).Once()
   470  
   471  				return converter
   472  			},
   473  			ExpectedErrorMessage: "",
   474  		},
   475  		{
   476  			Name:                    "Error when updating fails",
   477  			Context:                 ctx,
   478  			InputConstraintTemplate: formationConstraintModelInput,
   479  			FormationConstraintRepository: func() *automock.FormationConstraintRepository {
   480  				repo := &automock.FormationConstraintRepository{}
   481  				repo.On("Update", ctx, formationConstraintModel).Return(testErr).Once()
   482  				return repo
   483  			},
   484  			FormationConstraintConverter: func() *automock.FormationConstraintConverter {
   485  				converter := &automock.FormationConstraintConverter{}
   486  				converter.On("FromModelInputToModel", formationConstraintModelInput, testID).Return(formationConstraintModel).Once()
   487  
   488  				return converter
   489  			},
   490  			ExpectedErrorMessage: "while updating Formation Constraint with ID",
   491  		},
   492  	}
   493  
   494  	for _, testCase := range testCases {
   495  		t.Run(testCase.Name, func(t *testing.T) {
   496  			repo := UnusedFormationConstraintRepository()
   497  			if testCase.FormationConstraintRepository != nil {
   498  				repo = testCase.FormationConstraintRepository()
   499  			}
   500  			conv := UnusedFormationConstraintConverter()
   501  			if testCase.FormationConstraintConverter != nil {
   502  				conv = testCase.FormationConstraintConverter()
   503  			}
   504  			svc := formationconstraint.NewService(repo, nil, nil, conv)
   505  
   506  			// WHEN
   507  			err := svc.Update(testCase.Context, testID, testCase.InputConstraintTemplate)
   508  
   509  			// THEN
   510  			if testCase.ExpectedErrorMessage != "" {
   511  				require.Error(t, err)
   512  				assert.Contains(t, err.Error(), testCase.ExpectedErrorMessage)
   513  			} else {
   514  				assert.NoError(t, err)
   515  			}
   516  
   517  			mock.AssertExpectationsForObjects(t, repo, conv)
   518  		})
   519  	}
   520  }
   521  
   522  func TestService_ListByFormationTemplateIDs(t *testing.T) {
   523  	ctx := context.TODO()
   524  
   525  	testErr := errors.New("test err")
   526  	formationTemplateIDs := []string{formationTemplateID1, formationTemplateID2, formationTemplateID3}
   527  	constraintIDs := []string{constraintID1, constraintID2}
   528  
   529  	constraintRefs := []*model.FormationTemplateConstraintReference{
   530  		{
   531  			ConstraintID:        constraintIDs[0],
   532  			FormationTemplateID: formationTemplateIDs[0],
   533  		},
   534  		{
   535  			ConstraintID:        constraintIDs[1],
   536  			FormationTemplateID: formationTemplateIDs[1],
   537  		},
   538  		{
   539  			ConstraintID:        constraintIDs[1],
   540  			FormationTemplateID: formationTemplateIDs[2],
   541  		},
   542  	}
   543  
   544  	constraints := []*model.FormationConstraint{formationConstraint1, formationConstraint2, globalConstraint}
   545  
   546  	constraintsPerFormationTemplate := [][]*model.FormationConstraint{
   547  		{
   548  			formationConstraint1,
   549  			formationConstraint2,
   550  			globalConstraint,
   551  		},
   552  		{
   553  			formationConstraint1,
   554  			globalConstraint,
   555  		},
   556  	}
   557  
   558  	testCases := []struct {
   559  		Name                                     string
   560  		FormationTemplateConstraintReferenceRepo func() *automock.FormationTemplateConstraintReferenceRepository
   561  		FormationConstraintRepo                  func() *automock.FormationConstraintRepository
   562  		Input                                    []string
   563  		ExpectedConstraints                      [][]*model.FormationConstraint
   564  		ExpectedError                            error
   565  	}{
   566  		{
   567  			Name: "Success",
   568  			FormationTemplateConstraintReferenceRepo: func() *automock.FormationTemplateConstraintReferenceRepository {
   569  				refRepo := &automock.FormationTemplateConstraintReferenceRepository{}
   570  				refRepo.On("ListByFormationTemplateIDs", ctx, formationTemplateIDs).Return(constraintRefs, nil).Once()
   571  				return refRepo
   572  			},
   573  			FormationConstraintRepo: func() *automock.FormationConstraintRepository {
   574  				constraintRepo := &automock.FormationConstraintRepository{}
   575  				constraintRepo.On("ListByIDsAndGlobal", ctx, append(constraintIDs, constraintIDs[1])).Return(constraints, nil).Once()
   576  				return constraintRepo
   577  			},
   578  			Input:               formationTemplateIDs,
   579  			ExpectedConstraints: constraintsPerFormationTemplate,
   580  			ExpectedError:       nil,
   581  		},
   582  		{
   583  			Name: "Returns error when listing constraints fails",
   584  			FormationTemplateConstraintReferenceRepo: func() *automock.FormationTemplateConstraintReferenceRepository {
   585  				refRepo := &automock.FormationTemplateConstraintReferenceRepository{}
   586  				refRepo.On("ListByFormationTemplateIDs", ctx, formationTemplateIDs).Return(constraintRefs, nil).Once()
   587  				return refRepo
   588  			},
   589  			FormationConstraintRepo: func() *automock.FormationConstraintRepository {
   590  				constraintRepo := &automock.FormationConstraintRepository{}
   591  				constraintRepo.On("ListByIDsAndGlobal", ctx, append(constraintIDs, constraintIDs[1])).Return(nil, testErr).Once()
   592  				return constraintRepo
   593  			},
   594  			Input:               formationTemplateIDs,
   595  			ExpectedConstraints: nil,
   596  			ExpectedError:       testErr,
   597  		},
   598  		{
   599  			Name: "Returns error when listing constraints refs fails",
   600  			FormationTemplateConstraintReferenceRepo: func() *automock.FormationTemplateConstraintReferenceRepository {
   601  				refRepo := &automock.FormationTemplateConstraintReferenceRepository{}
   602  				refRepo.On("ListByFormationTemplateIDs", ctx, formationTemplateIDs).Return(nil, testErr).Once()
   603  				return refRepo
   604  			},
   605  			Input:               formationTemplateIDs,
   606  			ExpectedConstraints: nil,
   607  			ExpectedError:       testErr,
   608  		},
   609  	}
   610  
   611  	for _, testCase := range testCases {
   612  		t.Run(testCase.Name, func(t *testing.T) {
   613  			constraintRefRepo := testCase.FormationTemplateConstraintReferenceRepo()
   614  			constraintRepo := UnusedFormationConstraintRepository()
   615  			if testCase.FormationConstraintRepo != nil {
   616  				constraintRepo = testCase.FormationConstraintRepo()
   617  			}
   618  			svc := formationconstraint.NewService(constraintRepo, constraintRefRepo, nil, nil)
   619  
   620  			res, err := svc.ListByFormationTemplateIDs(ctx, testCase.Input)
   621  
   622  			if testCase.ExpectedError != nil {
   623  				require.Error(t, err)
   624  				require.Nil(t, res)
   625  			} else {
   626  				require.Nil(t, err)
   627  				reflect.DeepEqual(res, testCase.ExpectedConstraints)
   628  			}
   629  
   630  			mock.AssertExpectationsForObjects(t, constraintRefRepo, constraintRepo)
   631  		})
   632  	}
   633  }