github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/internal/repo/testdb/generic_repo_exist_tests.go (about) 1 package testdb 2 3 import ( 4 "context" 5 "fmt" 6 "reflect" 7 "testing" 8 9 "github.com/kyma-incubator/compass/components/director/pkg/apperrors" 10 "github.com/kyma-incubator/compass/components/director/pkg/persistence" 11 "github.com/pkg/errors" 12 "github.com/stretchr/testify/require" 13 ) 14 15 // RepoExistTestSuite represents a generic test suite for repository Exists method of any entity that has externally managed tenants in m2m table/view. 16 // This test suite is not suitable for global entities or entities with embedded tenant in them. 17 type RepoExistTestSuite struct { 18 Name string 19 SQLQueryDetails []SQLQueryDetails 20 ConverterMockProvider func() Mock 21 RepoConstructorFunc interface{} 22 TargetID string 23 TenantID string 24 RefEntity interface{} 25 IsGlobal bool 26 MethodName string 27 MethodArgs []interface{} 28 } 29 30 // Run runs the generic repo exists test suite 31 func (suite *RepoExistTestSuite) Run(t *testing.T) bool { 32 for _, queryDetails := range suite.SQLQueryDetails { 33 if !queryDetails.IsSelect { 34 panic("exist suite should expect only select SQL statements") 35 } 36 } 37 38 return t.Run(suite.Name, func(t *testing.T) { 39 testErr := errors.New("test error") 40 41 t.Run("success", func(t *testing.T) { 42 sqlxDB, sqlMock := MockDatabase(t) 43 ctx := persistence.SaveToContext(context.TODO(), sqlxDB) 44 45 configureValidSQLQueries(sqlMock, suite.SQLQueryDetails) 46 47 convMock := suite.ConverterMockProvider() 48 pgRepository := createRepo(suite.RepoConstructorFunc, convMock) 49 // WHEN 50 found, err := callExists(pgRepository, ctx, suite.MethodName, suite.MethodArgs) 51 // THEN 52 require.NoError(t, err) 53 require.True(t, found) 54 55 sqlMock.AssertExpectations(t) 56 convMock.AssertExpectations(t) 57 }) 58 59 t.Run("returns false if entity does not exist", func(t *testing.T) { 60 sqlxDB, sqlMock := MockDatabase(t) 61 ctx := persistence.SaveToContext(context.TODO(), sqlxDB) 62 63 configureInvalidSelect(sqlMock, suite.SQLQueryDetails) 64 65 convMock := suite.ConverterMockProvider() 66 pgRepository := createRepo(suite.RepoConstructorFunc, convMock) 67 // WHEN 68 found, err := callExists(pgRepository, ctx, suite.MethodName, suite.MethodArgs) 69 // THEN 70 require.NoError(t, err) 71 require.False(t, found) 72 73 sqlMock.AssertExpectations(t) 74 convMock.AssertExpectations(t) 75 }) 76 77 for i := range suite.SQLQueryDetails { 78 t.Run(fmt.Sprintf("error if SQL query %d fail", i), func(t *testing.T) { 79 sqlxDB, sqlMock := MockDatabase(t) 80 ctx := persistence.SaveToContext(context.TODO(), sqlxDB) 81 82 configureFailureForSQLQueryOnIndex(sqlMock, suite.SQLQueryDetails, i, testErr) 83 84 convMock := suite.ConverterMockProvider() 85 pgRepository := createRepo(suite.RepoConstructorFunc, convMock) 86 // WHEN 87 found, err := callExists(pgRepository, ctx, suite.MethodName, suite.MethodArgs) 88 // THEN 89 require.Error(t, err) 90 require.Equal(t, apperrors.InternalError, apperrors.ErrorCode(err)) 91 require.Contains(t, err.Error(), "Internal Server Error: Unexpected error while executing SQL query") 92 93 require.False(t, found) 94 95 sqlMock.AssertExpectations(t) 96 convMock.AssertExpectations(t) 97 }) 98 } 99 }) 100 } 101 102 func callExists(repo interface{}, ctx context.Context, methodName string, args []interface{}) (bool, error) { 103 argsVals := make([]reflect.Value, 1, len(args)) 104 argsVals[0] = reflect.ValueOf(ctx) 105 for _, arg := range args { 106 argsVals = append(argsVals, reflect.ValueOf(arg)) 107 } 108 109 results := reflect.ValueOf(repo).MethodByName(methodName).Call(argsVals) 110 if len(results) != 2 { 111 panic("Exists should return two arguments") 112 } 113 114 found := results[0].Bool() 115 errResult := results[1].Interface() 116 if errResult == nil { 117 return found, nil 118 } 119 err, ok := errResult.(error) 120 if !ok { 121 panic("Expected result to be an error") 122 } 123 return found, err 124 }