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

     1  package runtimectx_test
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  
     7  	"github.com/kyma-incubator/compass/components/director/internal/model"
     8  	"github.com/kyma-incubator/compass/components/director/pkg/graphql"
     9  	"github.com/kyma-incubator/compass/components/director/pkg/persistence/txtest"
    10  
    11  	runtimectx "github.com/kyma-incubator/compass/components/director/internal/domain/runtime_context"
    12  	"github.com/kyma-incubator/compass/components/director/pkg/consumer"
    13  
    14  	"github.com/kyma-incubator/compass/components/director/internal/domain/runtime_context/automock"
    15  
    16  	"github.com/kyma-incubator/compass/components/director/pkg/persistence"
    17  
    18  	"github.com/stretchr/testify/mock"
    19  
    20  	persistenceautomock "github.com/kyma-incubator/compass/components/director/pkg/persistence/automock"
    21  	"github.com/pkg/errors"
    22  	"github.com/stretchr/testify/assert"
    23  )
    24  
    25  var contextParam = mock.MatchedBy(func(ctx context.Context) bool {
    26  	persistenceOp, err := persistence.FromCtx(ctx)
    27  	return err == nil && persistenceOp != nil
    28  })
    29  
    30  func TestResolver_CreateRuntimeContext(t *testing.T) {
    31  	// GIVEN
    32  	id := "foo"
    33  	key := "key"
    34  	val := "value"
    35  	runtimeID := "runtime_id"
    36  
    37  	testErr := errors.New("Test error")
    38  	txGen := txtest.NewTransactionContextGenerator(testErr)
    39  
    40  	modelRuntimeContext := &model.RuntimeContext{
    41  		ID:        id,
    42  		RuntimeID: runtimeID,
    43  		Key:       key,
    44  		Value:     val,
    45  	}
    46  	gqlRuntimeContext := &graphql.RuntimeContext{
    47  		ID:    id,
    48  		Key:   key,
    49  		Value: val,
    50  	}
    51  
    52  	gqlInput := graphql.RuntimeContextInput{
    53  		Key:   key,
    54  		Value: val,
    55  	}
    56  	modelInput := model.RuntimeContextInput{
    57  		Key:       key,
    58  		Value:     val,
    59  		RuntimeID: runtimeID,
    60  	}
    61  
    62  	testCases := []struct {
    63  		Name            string
    64  		TransactionerFn func() (*persistenceautomock.PersistenceTx, *persistenceautomock.Transactioner)
    65  		ServiceFn       func() *automock.RuntimeContextService
    66  		ConverterFn     func() *automock.RuntimeContextConverter
    67  
    68  		Input                  graphql.RuntimeContextInput
    69  		ExpectedRuntimeContext *graphql.RuntimeContext
    70  		ExpectedErr            error
    71  		Consumer               *consumer.Consumer
    72  	}{
    73  		{
    74  			Name:            "Success",
    75  			TransactionerFn: txGen.ThatSucceeds,
    76  			ServiceFn: func() *automock.RuntimeContextService {
    77  				svc := &automock.RuntimeContextService{}
    78  				svc.On("GetByID", contextParam, "foo").Return(modelRuntimeContext, nil).Once()
    79  				svc.On("Create", contextParam, modelInput).Return("foo", nil).Once()
    80  				return svc
    81  			},
    82  			ConverterFn: func() *automock.RuntimeContextConverter {
    83  				conv := &automock.RuntimeContextConverter{}
    84  				conv.On("InputFromGraphQLWithRuntimeID", gqlInput, runtimeID).Return(modelInput).Once()
    85  				conv.On("ToGraphQL", modelRuntimeContext).Return(gqlRuntimeContext).Once()
    86  				return conv
    87  			},
    88  			Input:                  gqlInput,
    89  			ExpectedRuntimeContext: gqlRuntimeContext,
    90  			ExpectedErr:            nil,
    91  		},
    92  		{
    93  			Name:            "Returns error when transaction begin failed",
    94  			TransactionerFn: txGen.ThatFailsOnBegin,
    95  			ServiceFn: func() *automock.RuntimeContextService {
    96  				svc := &automock.RuntimeContextService{}
    97  				return svc
    98  			},
    99  			ConverterFn: func() *automock.RuntimeContextConverter {
   100  				conv := &automock.RuntimeContextConverter{}
   101  				conv.On("InputFromGraphQLWithRuntimeID", gqlInput, runtimeID).Return(modelInput).Once()
   102  				return conv
   103  			},
   104  			Input:                  gqlInput,
   105  			ExpectedRuntimeContext: nil,
   106  			ExpectedErr:            testErr,
   107  		},
   108  		{
   109  			Name:            "Returns error when runtime context creation failed",
   110  			TransactionerFn: txGen.ThatDoesntExpectCommit,
   111  			ServiceFn: func() *automock.RuntimeContextService {
   112  				svc := &automock.RuntimeContextService{}
   113  				svc.On("Create", contextParam, modelInput).Return("", testErr).Once()
   114  				return svc
   115  			},
   116  			ConverterFn: func() *automock.RuntimeContextConverter {
   117  				conv := &automock.RuntimeContextConverter{}
   118  				conv.On("InputFromGraphQLWithRuntimeID", gqlInput, runtimeID).Return(modelInput).Once()
   119  				return conv
   120  			},
   121  			Input:                  gqlInput,
   122  			ExpectedRuntimeContext: nil,
   123  			ExpectedErr:            testErr,
   124  		},
   125  		{
   126  			Name:            "Returns error when runtime context retrieval failed",
   127  			TransactionerFn: txGen.ThatDoesntExpectCommit,
   128  			ServiceFn: func() *automock.RuntimeContextService {
   129  				svc := &automock.RuntimeContextService{}
   130  				svc.On("Create", contextParam, modelInput).Return("foo", nil).Once()
   131  				svc.On("GetByID", contextParam, "foo").Return(nil, testErr).Once()
   132  				return svc
   133  			},
   134  			ConverterFn: func() *automock.RuntimeContextConverter {
   135  				conv := &automock.RuntimeContextConverter{}
   136  				conv.On("InputFromGraphQLWithRuntimeID", gqlInput, runtimeID).Return(modelInput).Once()
   137  				return conv
   138  			},
   139  			Input:                  gqlInput,
   140  			ExpectedRuntimeContext: nil,
   141  			ExpectedErr:            testErr,
   142  		},
   143  		{
   144  			Name:            "Returns error when transaction commit failed",
   145  			TransactionerFn: txGen.ThatFailsOnCommit,
   146  			ServiceFn: func() *automock.RuntimeContextService {
   147  				svc := &automock.RuntimeContextService{}
   148  				svc.On("GetByID", contextParam, "foo").Return(modelRuntimeContext, nil).Once()
   149  				svc.On("Create", contextParam, modelInput).Return("foo", nil).Once()
   150  				return svc
   151  			},
   152  			ConverterFn: func() *automock.RuntimeContextConverter {
   153  				conv := &automock.RuntimeContextConverter{}
   154  				conv.On("InputFromGraphQLWithRuntimeID", gqlInput, runtimeID).Return(modelInput).Once()
   155  				return conv
   156  			},
   157  			Input:                  gqlInput,
   158  			ExpectedRuntimeContext: nil,
   159  			ExpectedErr:            testErr,
   160  		},
   161  	}
   162  
   163  	for _, testCase := range testCases {
   164  		t.Run(testCase.Name, func(t *testing.T) {
   165  			persistTx, transact := testCase.TransactionerFn()
   166  			svc := testCase.ServiceFn()
   167  			converter := testCase.ConverterFn()
   168  
   169  			resolver := runtimectx.NewResolver(transact, svc, converter)
   170  
   171  			c := testCase.Consumer
   172  			if c == nil {
   173  				c = &consumer.Consumer{
   174  					ConsumerID:   runtimeID,
   175  					ConsumerType: consumer.Runtime,
   176  				}
   177  			}
   178  			ctx := consumer.SaveToContext(context.TODO(), *c)
   179  
   180  			// WHEN
   181  			result, err := resolver.RegisterRuntimeContext(ctx, runtimeID, testCase.Input)
   182  
   183  			// then
   184  			assert.Equal(t, testCase.ExpectedRuntimeContext, result)
   185  			assert.Equal(t, testCase.ExpectedErr, err)
   186  
   187  			mock.AssertExpectationsForObjects(t, svc, converter, transact, persistTx)
   188  		})
   189  	}
   190  }
   191  
   192  func TestResolver_UpdateRuntimeContext(t *testing.T) {
   193  	// GIVEN
   194  	id := "foo"
   195  	key := "key"
   196  	val := "value"
   197  	runtimeID := "runtime_id"
   198  
   199  	testErr := errors.New("Test error")
   200  	txGen := txtest.NewTransactionContextGenerator(testErr)
   201  
   202  	modelRuntimeContext := &model.RuntimeContext{
   203  		ID:        id,
   204  		RuntimeID: runtimeID,
   205  		Key:       key,
   206  		Value:     val,
   207  	}
   208  	gqlRuntimeContext := &graphql.RuntimeContext{
   209  		ID:    id,
   210  		Key:   key,
   211  		Value: val,
   212  	}
   213  
   214  	gqlInput := graphql.RuntimeContextInput{
   215  		Key:   key,
   216  		Value: val,
   217  	}
   218  	modelInput := model.RuntimeContextInput{
   219  		Key:       key,
   220  		Value:     val,
   221  		RuntimeID: runtimeID,
   222  	}
   223  
   224  	testCases := []struct {
   225  		Name                   string
   226  		TransactionerFn        func() (*persistenceautomock.PersistenceTx, *persistenceautomock.Transactioner)
   227  		ServiceFn              func() *automock.RuntimeContextService
   228  		ConverterFn            func() *automock.RuntimeContextConverter
   229  		RuntimeContextID       string
   230  		Input                  graphql.RuntimeContextInput
   231  		ExpectedRuntimeContext *graphql.RuntimeContext
   232  		ExpectedErr            error
   233  		Consumer               *consumer.Consumer
   234  	}{
   235  		{
   236  			Name:            "Success",
   237  			TransactionerFn: txGen.ThatSucceeds,
   238  			ServiceFn: func() *automock.RuntimeContextService {
   239  				svc := &automock.RuntimeContextService{}
   240  				svc.On("GetByID", contextParam, "foo").Return(modelRuntimeContext, nil).Once()
   241  				svc.On("Update", contextParam, id, modelInput).Return(nil).Once()
   242  				return svc
   243  			},
   244  			ConverterFn: func() *automock.RuntimeContextConverter {
   245  				conv := &automock.RuntimeContextConverter{}
   246  				conv.On("InputFromGraphQL", gqlInput).Return(modelInput).Once()
   247  				conv.On("ToGraphQL", modelRuntimeContext).Return(gqlRuntimeContext).Once()
   248  				return conv
   249  			},
   250  			RuntimeContextID:       id,
   251  			Input:                  gqlInput,
   252  			ExpectedRuntimeContext: gqlRuntimeContext,
   253  			ExpectedErr:            nil,
   254  		},
   255  		{
   256  			Name:            "Returns error when transaction begin failed",
   257  			TransactionerFn: txGen.ThatFailsOnBegin,
   258  			ServiceFn: func() *automock.RuntimeContextService {
   259  				svc := &automock.RuntimeContextService{}
   260  				return svc
   261  			},
   262  			ConverterFn: func() *automock.RuntimeContextConverter {
   263  				conv := &automock.RuntimeContextConverter{}
   264  				conv.On("InputFromGraphQL", gqlInput).Return(modelInput).Once()
   265  				return conv
   266  			},
   267  			Input:                  gqlInput,
   268  			ExpectedRuntimeContext: nil,
   269  			ExpectedErr:            testErr,
   270  		},
   271  		{
   272  			Name:            "Returns error when runtime context update failed",
   273  			TransactionerFn: txGen.ThatDoesntExpectCommit,
   274  			ServiceFn: func() *automock.RuntimeContextService {
   275  				svc := &automock.RuntimeContextService{}
   276  				svc.On("Update", contextParam, id, modelInput).Return(testErr).Once()
   277  				return svc
   278  			},
   279  			ConverterFn: func() *automock.RuntimeContextConverter {
   280  				conv := &automock.RuntimeContextConverter{}
   281  				conv.On("InputFromGraphQL", gqlInput).Return(modelInput).Once()
   282  				return conv
   283  			},
   284  			RuntimeContextID:       id,
   285  			Input:                  gqlInput,
   286  			ExpectedRuntimeContext: nil,
   287  			ExpectedErr:            testErr,
   288  		},
   289  		{
   290  			Name:            "Returns error when runtime context retrieval failed",
   291  			TransactionerFn: txGen.ThatDoesntExpectCommit,
   292  			ServiceFn: func() *automock.RuntimeContextService {
   293  				svc := &automock.RuntimeContextService{}
   294  				svc.On("Update", contextParam, id, modelInput).Return(nil).Once()
   295  				svc.On("GetByID", contextParam, "foo").Return(nil, testErr).Once()
   296  				return svc
   297  			},
   298  			ConverterFn: func() *automock.RuntimeContextConverter {
   299  				conv := &automock.RuntimeContextConverter{}
   300  				conv.On("InputFromGraphQL", gqlInput).Return(modelInput).Once()
   301  				return conv
   302  			},
   303  			RuntimeContextID:       id,
   304  			Input:                  gqlInput,
   305  			ExpectedRuntimeContext: nil,
   306  			ExpectedErr:            testErr,
   307  		},
   308  		{
   309  			Name:            "Returns error when transaction commit failed",
   310  			TransactionerFn: txGen.ThatFailsOnCommit,
   311  			ServiceFn: func() *automock.RuntimeContextService {
   312  				svc := &automock.RuntimeContextService{}
   313  				svc.On("GetByID", contextParam, "foo").Return(modelRuntimeContext, nil).Once()
   314  				svc.On("Update", contextParam, id, modelInput).Return(nil).Once()
   315  				return svc
   316  			},
   317  			ConverterFn: func() *automock.RuntimeContextConverter {
   318  				conv := &automock.RuntimeContextConverter{}
   319  				conv.On("InputFromGraphQL", gqlInput).Return(modelInput).Once()
   320  				return conv
   321  			},
   322  			RuntimeContextID:       id,
   323  			Input:                  gqlInput,
   324  			ExpectedRuntimeContext: nil,
   325  			ExpectedErr:            testErr,
   326  		},
   327  	}
   328  
   329  	for _, testCase := range testCases {
   330  		t.Run(testCase.Name, func(t *testing.T) {
   331  			persistTx, transact := testCase.TransactionerFn()
   332  			svc := testCase.ServiceFn()
   333  			converter := testCase.ConverterFn()
   334  
   335  			resolver := runtimectx.NewResolver(transact, svc, converter)
   336  
   337  			c := testCase.Consumer
   338  			if c == nil {
   339  				c = &consumer.Consumer{
   340  					ConsumerID:   runtimeID,
   341  					ConsumerType: consumer.Runtime,
   342  				}
   343  			}
   344  			ctx := consumer.SaveToContext(context.TODO(), *c)
   345  
   346  			// WHEN
   347  			result, err := resolver.UpdateRuntimeContext(ctx, testCase.RuntimeContextID, testCase.Input)
   348  
   349  			// then
   350  			assert.Equal(t, testCase.ExpectedRuntimeContext, result)
   351  			assert.Equal(t, testCase.ExpectedErr, err)
   352  
   353  			mock.AssertExpectationsForObjects(t, svc, converter, transact, persistTx)
   354  		})
   355  	}
   356  }
   357  
   358  func TestResolver_DeleteRuntimeContext(t *testing.T) {
   359  	// GIVEN
   360  	id := "foo"
   361  	key := "key"
   362  	val := "value"
   363  	runtimeID := "runtime_id"
   364  
   365  	testErr := errors.New("Test error")
   366  	txGen := txtest.NewTransactionContextGenerator(testErr)
   367  
   368  	modelRuntimeContext := &model.RuntimeContext{
   369  		ID:        id,
   370  		RuntimeID: runtimeID,
   371  		Key:       key,
   372  		Value:     val,
   373  	}
   374  	gqlRuntimeContext := &graphql.RuntimeContext{
   375  		ID:    id,
   376  		Key:   key,
   377  		Value: val,
   378  	}
   379  
   380  	testCases := []struct {
   381  		Name                   string
   382  		TransactionerFn        func() (*persistenceautomock.PersistenceTx, *persistenceautomock.Transactioner)
   383  		ServiceFn              func() *automock.RuntimeContextService
   384  		ConverterFn            func() *automock.RuntimeContextConverter
   385  		InputID                string
   386  		ExpectedRuntimeContext *graphql.RuntimeContext
   387  		ExpectedErr            error
   388  		Consumer               *consumer.Consumer
   389  	}{
   390  		{
   391  			Name:            "Success",
   392  			TransactionerFn: txGen.ThatSucceeds,
   393  			ServiceFn: func() *automock.RuntimeContextService {
   394  				svc := &automock.RuntimeContextService{}
   395  				svc.On("GetByID", contextParam, "foo").Return(modelRuntimeContext, nil).Once()
   396  				svc.On("Delete", contextParam, "foo").Return(nil).Once()
   397  				return svc
   398  			},
   399  			ConverterFn: func() *automock.RuntimeContextConverter {
   400  				conv := &automock.RuntimeContextConverter{}
   401  				conv.On("ToGraphQL", modelRuntimeContext).Return(gqlRuntimeContext).Once()
   402  				return conv
   403  			},
   404  			InputID:                id,
   405  			ExpectedRuntimeContext: gqlRuntimeContext,
   406  			ExpectedErr:            nil,
   407  		},
   408  		{
   409  			Name:            "Returns error when runtime context deletion failed",
   410  			TransactionerFn: txGen.ThatDoesntExpectCommit,
   411  			ServiceFn: func() *automock.RuntimeContextService {
   412  				svc := &automock.RuntimeContextService{}
   413  				svc.On("GetByID", contextParam, "foo").Return(modelRuntimeContext, nil).Once()
   414  				svc.On("Delete", contextParam, "foo").Return(testErr).Once()
   415  				return svc
   416  			},
   417  			ConverterFn: func() *automock.RuntimeContextConverter {
   418  				conv := &automock.RuntimeContextConverter{}
   419  				return conv
   420  			},
   421  			InputID:                id,
   422  			ExpectedRuntimeContext: nil,
   423  			ExpectedErr:            testErr,
   424  		},
   425  		{
   426  			Name:            "Returns error when runtime context retrieval failed",
   427  			TransactionerFn: txGen.ThatDoesntExpectCommit,
   428  			ServiceFn: func() *automock.RuntimeContextService {
   429  				svc := &automock.RuntimeContextService{}
   430  				svc.On("GetByID", contextParam, "foo").Return(nil, testErr).Once()
   431  				return svc
   432  			},
   433  			ConverterFn: func() *automock.RuntimeContextConverter {
   434  				conv := &automock.RuntimeContextConverter{}
   435  				return conv
   436  			},
   437  			InputID:                id,
   438  			ExpectedRuntimeContext: nil,
   439  			ExpectedErr:            testErr,
   440  		},
   441  		{
   442  			Name:            "Returns error when transaction starting failed",
   443  			TransactionerFn: txGen.ThatFailsOnBegin,
   444  			ServiceFn: func() *automock.RuntimeContextService {
   445  				svc := &automock.RuntimeContextService{}
   446  				return svc
   447  			},
   448  			ConverterFn: func() *automock.RuntimeContextConverter {
   449  				conv := &automock.RuntimeContextConverter{}
   450  				return conv
   451  			},
   452  			InputID:                id,
   453  			ExpectedRuntimeContext: nil,
   454  			ExpectedErr:            testErr,
   455  		},
   456  		{
   457  			Name:            "Returns error when transaction commit failed",
   458  			TransactionerFn: txGen.ThatFailsOnCommit,
   459  			ServiceFn: func() *automock.RuntimeContextService {
   460  				svc := &automock.RuntimeContextService{}
   461  				svc.On("GetByID", contextParam, "foo").Return(modelRuntimeContext, nil).Once()
   462  				svc.On("Delete", contextParam, modelRuntimeContext.ID).Return(nil)
   463  				return svc
   464  			},
   465  			ConverterFn: func() *automock.RuntimeContextConverter {
   466  				conv := &automock.RuntimeContextConverter{}
   467  				return conv
   468  			},
   469  			InputID:                id,
   470  			ExpectedRuntimeContext: nil,
   471  			ExpectedErr:            testErr,
   472  		},
   473  	}
   474  
   475  	for _, testCase := range testCases {
   476  		t.Run(testCase.Name, func(t *testing.T) {
   477  			persistTx, transact := testCase.TransactionerFn()
   478  			svc := testCase.ServiceFn()
   479  			converter := testCase.ConverterFn()
   480  
   481  			resolver := runtimectx.NewResolver(transact, svc, converter)
   482  
   483  			c := testCase.Consumer
   484  			if c == nil {
   485  				c = &consumer.Consumer{
   486  					ConsumerID:   runtimeID,
   487  					ConsumerType: consumer.Runtime,
   488  				}
   489  			}
   490  			ctx := consumer.SaveToContext(context.TODO(), *c)
   491  
   492  			// WHEN
   493  			result, err := resolver.DeleteRuntimeContext(ctx, testCase.InputID)
   494  
   495  			// then
   496  			assert.Equal(t, testCase.ExpectedRuntimeContext, result)
   497  			if testCase.ExpectedErr != nil {
   498  				assert.EqualError(t, testCase.ExpectedErr, err.Error())
   499  			} else {
   500  				assert.NoError(t, err)
   501  			}
   502  
   503  			mock.AssertExpectationsForObjects(t, svc, converter, transact, persistTx)
   504  		})
   505  	}
   506  }
   507  
   508  func TestResolver_Labels(t *testing.T) {
   509  	// GIVEN
   510  	id := "foo"
   511  	labelKey1 := "key1"
   512  	labelValue1 := "val1"
   513  	labelKey2 := "key2"
   514  	labelValue2 := "val2"
   515  
   516  	key := "key1"
   517  	val := "value1"
   518  
   519  	testErr := errors.New("Test error")
   520  	txGen := txtest.NewTransactionContextGenerator(testErr)
   521  
   522  	gqlRuntimeContext := &graphql.RuntimeContext{
   523  		ID:    id,
   524  		Key:   key,
   525  		Value: val,
   526  	}
   527  
   528  	modelLabels := map[string]*model.Label{
   529  		"abc": {
   530  			ID:         "abc",
   531  			Key:        labelKey1,
   532  			Value:      labelValue1,
   533  			ObjectID:   id,
   534  			ObjectType: model.RuntimeContextLabelableObject,
   535  		},
   536  		"def": {
   537  			ID:         "def",
   538  			Key:        labelKey2,
   539  			Value:      labelValue2,
   540  			ObjectID:   id,
   541  			ObjectType: model.RuntimeContextLabelableObject,
   542  		},
   543  	}
   544  
   545  	gqlLabels := graphql.Labels{
   546  		labelKey1: labelValue1,
   547  		labelKey2: labelValue2,
   548  	}
   549  
   550  	gqlLabels1 := graphql.Labels{
   551  		labelKey1: labelValue1,
   552  	}
   553  
   554  	testCases := []struct {
   555  		Name                string
   556  		TransactionerFn     func() (*persistenceautomock.PersistenceTx, *persistenceautomock.Transactioner)
   557  		ServiceFn           func() *automock.RuntimeContextService
   558  		InputRuntimeContext *graphql.RuntimeContext
   559  		InputKey            *string
   560  		ExpectedResult      graphql.Labels
   561  		ExpectedErr         error
   562  	}{
   563  		{
   564  			Name:            "Success",
   565  			TransactionerFn: txGen.ThatSucceeds,
   566  			ServiceFn: func() *automock.RuntimeContextService {
   567  				svc := &automock.RuntimeContextService{}
   568  				svc.On("ListLabels", contextParam, id).Return(modelLabels, nil).Once()
   569  				return svc
   570  			},
   571  			InputKey:       nil,
   572  			ExpectedResult: gqlLabels,
   573  			ExpectedErr:    nil,
   574  		},
   575  		{
   576  			Name:            "Success when labels are filtered",
   577  			TransactionerFn: txGen.ThatSucceeds,
   578  			ServiceFn: func() *automock.RuntimeContextService {
   579  				svc := &automock.RuntimeContextService{}
   580  				svc.On("ListLabels", contextParam, id).Return(modelLabels, nil).Once()
   581  				return svc
   582  			},
   583  			InputKey:       &labelKey1,
   584  			ExpectedResult: gqlLabels1,
   585  			ExpectedErr:    nil,
   586  		},
   587  		{
   588  			Name:            "Success returns nil when labels not found",
   589  			TransactionerFn: txGen.ThatSucceeds,
   590  			ServiceFn: func() *automock.RuntimeContextService {
   591  				svc := &automock.RuntimeContextService{}
   592  				svc.On("ListLabels", contextParam, id).Return(nil, errors.New("doesn't exist")).Once()
   593  				return svc
   594  			},
   595  			InputKey:       &labelKey1,
   596  			ExpectedResult: nil,
   597  			ExpectedErr:    nil,
   598  		},
   599  		{
   600  			Name:            "Returns error when transaction begin failed",
   601  			TransactionerFn: txGen.ThatFailsOnBegin,
   602  			ServiceFn: func() *automock.RuntimeContextService {
   603  				svc := &automock.RuntimeContextService{}
   604  				return svc
   605  			},
   606  			InputKey:       &labelKey1,
   607  			ExpectedResult: nil,
   608  			ExpectedErr:    testErr,
   609  		},
   610  		{
   611  			Name:            "Returns error when label listing failed",
   612  			TransactionerFn: txGen.ThatDoesntExpectCommit,
   613  			ServiceFn: func() *automock.RuntimeContextService {
   614  				svc := &automock.RuntimeContextService{}
   615  				svc.On("ListLabels", contextParam, id).Return(nil, testErr).Once()
   616  				return svc
   617  			},
   618  			InputKey:       &labelKey1,
   619  			ExpectedResult: nil,
   620  			ExpectedErr:    testErr,
   621  		},
   622  		{
   623  			Name:            "Returns error when transaction commit failed",
   624  			TransactionerFn: txGen.ThatFailsOnCommit,
   625  			ServiceFn: func() *automock.RuntimeContextService {
   626  				svc := &automock.RuntimeContextService{}
   627  				svc.On("ListLabels", contextParam, id).Return(modelLabels, nil).Once()
   628  				return svc
   629  			},
   630  			InputKey:       nil,
   631  			ExpectedResult: nil,
   632  			ExpectedErr:    testErr,
   633  		},
   634  	}
   635  
   636  	for _, testCase := range testCases {
   637  		t.Run(testCase.Name, func(t *testing.T) {
   638  			persistTx, transact := testCase.TransactionerFn()
   639  			svc := testCase.ServiceFn()
   640  
   641  			resolver := runtimectx.NewResolver(transact, svc, nil)
   642  
   643  			// WHEN
   644  			result, err := resolver.Labels(context.TODO(), gqlRuntimeContext, testCase.InputKey)
   645  
   646  			// then
   647  			assert.Equal(t, testCase.ExpectedResult, result)
   648  			assert.Equal(t, testCase.ExpectedErr, err)
   649  
   650  			mock.AssertExpectationsForObjects(t, svc, transact, persistTx)
   651  		})
   652  	}
   653  }