Repository: go-to-k/delstack
Pull request #95 (2023-02-01 10:02:39)

test: gomock


Patch:
diff --git a/Makefile b/Makefile
index 0c855de..7786734 100644
--- a/Makefile
+++ b/Makefile
@@ -21,6 +21,8 @@ test:
 test_view:
 	@! echo $(TEST_COV_RESULT) | $(COLORIZE_PASS) | $(COLORIZE_FAIL) | tee /dev/stderr | grep $(FAIL_CHECK) > /dev/null
 	go tool cover -html=cover_file.out -o cover_file.html
+mockgen:
+	go generate ./...
 shadow:
 	find . -type f -name '*.go' | sed -e "s/\/[^\.\/]*\.go//g" | uniq | xargs shadow
 run:
diff --git a/go.mod b/go.mod
index e2e8232..72ed858 100644
--- a/go.mod
+++ b/go.mod
@@ -34,6 +34,7 @@ require (
 	github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.8 // indirect
 	github.com/aws/aws-sdk-go-v2/service/sts v1.17.2 // indirect
 	github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
+	github.com/golang/mock v1.6.0 // indirect
 	github.com/jmespath/go-jmespath v0.4.0 // indirect
 	github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
 	github.com/mattn/go-colorable v0.1.12 // indirect
diff --git a/go.sum b/go.sum
index bc845e1..bf2570b 100644
--- a/go.sum
+++ b/go.sum
@@ -67,6 +67,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
+github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
+github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
 github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
 github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog=
@@ -104,20 +106,40 @@ github.com/urfave/cli/v2 v2.23.0 h1:pkly7gKIeYv3olPAeNajNpLjeJrmTPYCoZWaV+2VfvE=
 github.com/urfave/cli/v2 v2.23.0/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI=
 github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
 github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
+github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde h1:ejfdSekXMDxDLbRrJMwUk6KnSLZ2McaUCVcIKM+N6jc=
 golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 h1:xHms4gcpe1YE7A3yIllJXP16CMAGuqwO2lX1mTyyRRc=
 golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210503060354-a79de5458b56 h1:b8jxX3zqjpqb2LklXPzKSGJhzyxCOZSz8ncv8Nv+y7w=
 golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
 gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
diff --git a/internal/operation/operator.go b/internal/operation/operator.go
index 15e8d8b..bf6cf26 100644
--- a/internal/operation/operator.go
+++ b/internal/operation/operator.go
@@ -1,3 +1,4 @@
+//go:generate mockgen -source=./operator.go -destination=./operator_mock.go -package=operation
 package operation
 
 import (
diff --git a/internal/operation/operator_collection.go b/internal/operation/operator_collection.go
index e461eb2..7294e4d 100644
--- a/internal/operation/operator_collection.go
+++ b/internal/operation/operator_collection.go
@@ -1,3 +1,4 @@
+//go:generate mockgen -source=./operator_collection.go -destination=./operator_collection_mock.go -package=operation
 package operation
 
 import (
@@ -21,14 +22,14 @@ var _ IOperatorCollection = (*OperatorCollection)(nil)
 
 type OperatorCollection struct {
 	stackName                 string
-	operatorFactory           IOperatorFactory
+	operatorFactory           *OperatorFactory
 	logicalResourceIds        []string
 	unsupportedStackResources []types.StackResourceSummary
 	operators                 []IOperator
 	targetResourceTypes       []string
 }
 
-func NewOperatorCollection(config aws.Config, operatorFactory IOperatorFactory, targetResourceTypes []string) *OperatorCollection {
+func NewOperatorCollection(config aws.Config, operatorFactory *OperatorFactory, targetResourceTypes []string) *OperatorCollection {
 	return &OperatorCollection{
 		operatorFactory:     operatorFactory,
 		targetResourceTypes: targetResourceTypes,
diff --git a/internal/operation/operator_collection_mock.go b/internal/operation/operator_collection_mock.go
index fb04440..1d89ddd 100644
--- a/internal/operation/operator_collection_mock.go
+++ b/internal/operation/operator_collection_mock.go
@@ -1,143 +1,89 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: ./operator_collection.go
+
+// Package operation is a generated GoMock package.
 package operation
 
 import (
-	"fmt"
+	reflect "reflect"
 
-	"github.com/aws/aws-sdk-go-v2/service/cloudformation/types"
+	types "github.com/aws/aws-sdk-go-v2/service/cloudformation/types"
+	gomock "github.com/golang/mock/gomock"
 )
 
-/*
-	Mocks for OperatorCollection
-*/
-
-var _ IOperatorCollection = (*MockOperatorCollection)(nil)
-var _ IOperatorCollection = (*IncorrectResourceCountsMockOperatorCollection)(nil)
-var _ IOperatorCollection = (*OperatorDeleteResourcesMockOperatorCollection)(nil)
-
-type MockOperatorCollection struct{}
-
-func NewMockOperatorCollection() *MockOperatorCollection {
-	return &MockOperatorCollection{}
+// MockIOperatorCollection is a mock of IOperatorCollection interface.
+type MockIOperatorCollection struct {
+	ctrl     *gomock.Controller
+	recorder *MockIOperatorCollectionMockRecorder
 }
 
-func (m *MockOperatorCollection) SetOperatorCollection(stackName *string, stackResourceSummaries []types.StackResourceSummary) {
+// MockIOperatorCollectionMockRecorder is the mock recorder for MockIOperatorCollection.
+type MockIOperatorCollectionMockRecorder struct {
+	mock *MockIOperatorCollection
 }
 
-func (m *MockOperatorCollection) GetLogicalResourceIds() []string {
-	return []string{
-		"logicalResourceId1",
-		"logicalResourceId2",
-		"logicalResourceId3",
-		"logicalResourceId4",
-		"logicalResourceId5",
-		"logicalResourceId6",
-	}
+// NewMockIOperatorCollection creates a new mock instance.
+func NewMockIOperatorCollection(ctrl *gomock.Controller) *MockIOperatorCollection {
+	mock := &MockIOperatorCollection{ctrl: ctrl}
+	mock.recorder = &MockIOperatorCollectionMockRecorder{mock}
+	return mock
 }
 
-func (m *MockOperatorCollection) GetOperators() []IOperator {
-	var operators []IOperator
-
-	cloudformationStackOperator := NewMockCloudFormationStackOperator()
-	s3BucketOperator := NewMockS3BucketOperator()
-	iamRoleOperator := NewMockIamRoleOperator()
-	ecrRepositoryOperator := NewMockEcrRepositoryOperator()
-	backupVaultOperator := NewMockBackupVaultOperator()
-	customOperator := NewMockCustomOperator()
-
-	operators = append(operators, cloudformationStackOperator)
-	operators = append(operators, s3BucketOperator)
-	operators = append(operators, iamRoleOperator)
-	operators = append(operators, ecrRepositoryOperator)
-	operators = append(operators, backupVaultOperator)
-	operators = append(operators, customOperator)
-
-	return operators
+// EXPECT returns an object that allows the caller to indicate expected use.
+func (m *MockIOperatorCollection) EXPECT() *MockIOperatorCollectionMockRecorder {
+	return m.recorder
 }
 
-func (m *MockOperatorCollection) RaiseUnsupportedResourceError() error {
-	return fmt.Errorf("UnsupportedResourceError")
+// GetLogicalResourceIds mocks base method.
+func (m *MockIOperatorCollection) GetLogicalResourceIds() []string {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "GetLogicalResourceIds")
+	ret0, _ := ret[0].([]string)
+	return ret0
 }
 
-type IncorrectResourceCountsMockOperatorCollection struct{}
-
-func NewIncorrectResourceCountsMockOperatorCollection() *IncorrectResourceCountsMockOperatorCollection {
-	return &IncorrectResourceCountsMockOperatorCollection{}
+// GetLogicalResourceIds indicates an expected call of GetLogicalResourceIds.
+func (mr *MockIOperatorCollectionMockRecorder) GetLogicalResourceIds() *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLogicalResourceIds", reflect.TypeOf((*MockIOperatorCollection)(nil).GetLogicalResourceIds))
 }
 
-func (m *IncorrectResourceCountsMockOperatorCollection) SetOperatorCollection(stackName *string, stackResourceSummaries []types.StackResourceSummary) {
+// GetOperators mocks base method.
+func (m *MockIOperatorCollection) GetOperators() []IOperator {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "GetOperators")
+	ret0, _ := ret[0].([]IOperator)
+	return ret0
 }
 
-func (m *IncorrectResourceCountsMockOperatorCollection) GetLogicalResourceIds() []string {
-	return []string{
-		"logicalResourceId1",
-		"logicalResourceId2",
-	}
+// GetOperators indicates an expected call of GetOperators.
+func (mr *MockIOperatorCollectionMockRecorder) GetOperators() *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetOperators", reflect.TypeOf((*MockIOperatorCollection)(nil).GetOperators))
 }
 
-func (m *IncorrectResourceCountsMockOperatorCollection) GetOperators() []IOperator {
-	var operators []IOperator
-
-	cloudformationStackOperator := NewMockCloudFormationStackOperator()
-	s3BucketOperator := NewMockS3BucketOperator()
-	iamRoleOperator := NewMockIamRoleOperator()
-	ecrRepositoryOperator := NewMockEcrRepositoryOperator()
-	backupVaultOperator := NewMockBackupVaultOperator()
-	customOperator := NewMockCustomOperator()
-
-	operators = append(operators, cloudformationStackOperator)
-	operators = append(operators, s3BucketOperator)
-	operators = append(operators, iamRoleOperator)
-	operators = append(operators, ecrRepositoryOperator)
-	operators = append(operators, backupVaultOperator)
-	operators = append(operators, customOperator)
-
-	return operators
+// RaiseUnsupportedResourceError mocks base method.
+func (m *MockIOperatorCollection) RaiseUnsupportedResourceError() error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "RaiseUnsupportedResourceError")
+	ret0, _ := ret[0].(error)
+	return ret0
 }
 
-func (m *IncorrectResourceCountsMockOperatorCollection) RaiseUnsupportedResourceError() error {
-	return fmt.Errorf("UnsupportedResourceError")
+// RaiseUnsupportedResourceError indicates an expected call of RaiseUnsupportedResourceError.
+func (mr *MockIOperatorCollectionMockRecorder) RaiseUnsupportedResourceError() *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RaiseUnsupportedResourceError", reflect.TypeOf((*MockIOperatorCollection)(nil).RaiseUnsupportedResourceError))
 }
 
-type OperatorDeleteResourcesMockOperatorCollection struct{}
-
-func NewOperatorDeleteResourcesMockOperatorCollection() *OperatorDeleteResourcesMockOperatorCollection {
-	return &OperatorDeleteResourcesMockOperatorCollection{}
-}
-
-func (m *OperatorDeleteResourcesMockOperatorCollection) SetOperatorCollection(stackName *string, stackResourceSummaries []types.StackResourceSummary) {
-}
-
-func (m *OperatorDeleteResourcesMockOperatorCollection) GetLogicalResourceIds() []string {
-	return []string{
-		"logicalResourceId1",
-		"logicalResourceId2",
-		"logicalResourceId3",
-		"logicalResourceId4",
-		"logicalResourceId5",
-		"logicalResourceId6",
-	}
-}
-
-func (m *OperatorDeleteResourcesMockOperatorCollection) GetOperators() []IOperator {
-	var operators []IOperator
-
-	cloudformationStackOperator := NewErrorMockCloudFormationStackOperator()
-	s3BucketOperator := NewMockS3BucketOperator()
-	iamRoleOperator := NewMockIamRoleOperator()
-	ecrRepositoryOperator := NewMockEcrRepositoryOperator()
-	backupVaultOperator := NewMockBackupVaultOperator()
-	customOperator := NewMockCustomOperator()
-
-	operators = append(operators, cloudformationStackOperator)
-	operators = append(operators, s3BucketOperator)
-	operators = append(operators, iamRoleOperator)
-	operators = append(operators, ecrRepositoryOperator)
-	operators = append(operators, backupVaultOperator)
-	operators = append(operators, customOperator)
-
-	return operators
+// SetOperatorCollection mocks base method.
+func (m *MockIOperatorCollection) SetOperatorCollection(stackName *string, stackResourceSummaries []types.StackResourceSummary) {
+	m.ctrl.T.Helper()
+	m.ctrl.Call(m, "SetOperatorCollection", stackName, stackResourceSummaries)
 }
 
-func (m *OperatorDeleteResourcesMockOperatorCollection) RaiseUnsupportedResourceError() error {
-	return fmt.Errorf("UnsupportedResourceError")
+// SetOperatorCollection indicates an expected call of SetOperatorCollection.
+func (mr *MockIOperatorCollectionMockRecorder) SetOperatorCollection(stackName, stackResourceSummaries interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetOperatorCollection", reflect.TypeOf((*MockIOperatorCollection)(nil).SetOperatorCollection), stackName, stackResourceSummaries)
 }
diff --git a/internal/operation/operator_factory.go b/internal/operation/operator_factory.go
index 447530e..4ca00a6 100644
--- a/internal/operation/operator_factory.go
+++ b/internal/operation/operator_factory.go
@@ -12,17 +12,6 @@ import (
 
 const SDKRetryMaxAttempts = 3
 
-type IOperatorFactory interface {
-	CreateCloudFormationStackOperator(targetResourceTypes []string) *CloudFormationStackOperator
-	CreateBackupVaultOperator() *BackupVaultOperator
-	CreateEcrRepositoryOperator() *EcrRepositoryOperator
-	CreateIamRoleOperator() *IamRoleOperator
-	CreateS3BucketOperator() *S3BucketOperator
-	CreateCustomOperator() *CustomOperator
-}
-
-var _ IOperatorFactory = (*OperatorFactory)(nil)
-
 type OperatorFactory struct {
 	config aws.Config
 }
diff --git a/internal/operation/operator_manager.go b/internal/operation/operator_manager.go
index 1802992..348b817 100644
--- a/internal/operation/operator_manager.go
+++ b/internal/operation/operator_manager.go
@@ -1,3 +1,4 @@
+//go:generate mockgen -source=./operator_manager.go -destination=./operator_manager_mock.go -package=operation
 package operation
 
 import (
diff --git a/internal/operation/operator_manager_mock.go b/internal/operation/operator_manager_mock.go
index a4c808c..96d9895 100644
--- a/internal/operation/operator_manager_mock.go
+++ b/internal/operation/operator_manager_mock.go
@@ -1,101 +1,90 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: ./operator_manager.go
+
+// Package operation is a generated GoMock package.
 package operation
 
 import (
-	"context"
-	"fmt"
+	context "context"
+	reflect "reflect"
 
-	"github.com/aws/aws-sdk-go-v2/service/cloudformation/types"
+	types "github.com/aws/aws-sdk-go-v2/service/cloudformation/types"
+	gomock "github.com/golang/mock/gomock"
 )
 
-/*
-	Mocks for OperatorManager
-*/
-
-var _ IOperatorManager = (*MockOperatorManager)(nil)
-var _ IOperatorManager = (*AllErrorMockOperatorManager)(nil)
-var _ IOperatorManager = (*CheckResourceCountsErrorMockOperatorManager)(nil)
-var _ IOperatorManager = (*DeleteResourceCollectionErrorMockOperatorManager)(nil)
-
-type MockOperatorManager struct{}
-
-func NewMockOperatorManager() *MockOperatorManager {
-	return &MockOperatorManager{}
-}
-
-func (m *MockOperatorManager) SetOperatorCollection(stackName *string, stackResourceSummaries []types.StackResourceSummary) {
+// MockIOperatorManager is a mock of IOperatorManager interface.
+type MockIOperatorManager struct {
+	ctrl     *gomock.Controller
+	recorder *MockIOperatorManagerMockRecorder
 }
 
-func (m *MockOperatorManager) CheckResourceCounts() error {
-	return nil
+// MockIOperatorManagerMockRecorder is the mock recorder for MockIOperatorManager.
+type MockIOperatorManagerMockRecorder struct {
+	mock *MockIOperatorManager
 }
 
-func (m *MockOperatorManager) GetLogicalResourceIds() []string {
-	return []string{"logicalResourceId1", "logicalResourceId2"}
+// NewMockIOperatorManager creates a new mock instance.
+func NewMockIOperatorManager(ctrl *gomock.Controller) *MockIOperatorManager {
+	mock := &MockIOperatorManager{ctrl: ctrl}
+	mock.recorder = &MockIOperatorManagerMockRecorder{mock}
+	return mock
 }
 
-func (m *MockOperatorManager) DeleteResourceCollection(ctx context.Context) error {
-	return nil
+// EXPECT returns an object that allows the caller to indicate expected use.
+func (m *MockIOperatorManager) EXPECT() *MockIOperatorManagerMockRecorder {
+	return m.recorder
 }
 
-type AllErrorMockOperatorManager struct{}
-
-func NewAllErrorMockOperatorManager() *AllErrorMockOperatorManager {
-	return &AllErrorMockOperatorManager{}
-}
-
-func (m *AllErrorMockOperatorManager) SetOperatorCollection(stackName *string, stackResourceSummaries []types.StackResourceSummary) {
+// CheckResourceCounts mocks base method.
+func (m *MockIOperatorManager) CheckResourceCounts() error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "CheckResourceCounts")
+	ret0, _ := ret[0].(error)
+	return ret0
 }
 
-func (m *AllErrorMockOperatorManager) CheckResourceCounts() error {
-	return fmt.Errorf("CheckResourceCountsError")
+// CheckResourceCounts indicates an expected call of CheckResourceCounts.
+func (mr *MockIOperatorManagerMockRecorder) CheckResourceCounts() *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckResourceCounts", reflect.TypeOf((*MockIOperatorManager)(nil).CheckResourceCounts))
 }
 
-func (m *AllErrorMockOperatorManager) GetLogicalResourceIds() []string {
-	return []string{"logicalResourceId1", "logicalResourceId2"}
+// DeleteResourceCollection mocks base method.
+func (m *MockIOperatorManager) DeleteResourceCollection(ctx context.Context) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DeleteResourceCollection", ctx)
+	ret0, _ := ret[0].(error)
+	return ret0
 }
 
-func (m *AllErrorMockOperatorManager) DeleteResourceCollection(ctx context.Context) error {
-	return fmt.Errorf("DeleteResourceCollectionError")
-}
-
-type CheckResourceCountsErrorMockOperatorManager struct{}
-
-func NewCheckResourceCountsErrorMockOperatorManager() *CheckResourceCountsErrorMockOperatorManager {
-	return &CheckResourceCountsErrorMockOperatorManager{}
-}
-
-func (m *CheckResourceCountsErrorMockOperatorManager) SetOperatorCollection(stackName *string, stackResourceSummaries []types.StackResourceSummary) {
-}
-
-func (m *CheckResourceCountsErrorMockOperatorManager) CheckResourceCounts() error {
-	return fmt.Errorf("CheckResourceCountsError")
-}
-
-func (m *CheckResourceCountsErrorMockOperatorManager) GetLogicalResourceIds() []string {
-	return []string{"logicalResourceId1", "logicalResourceId2"}
-}
-
-func (m *CheckResourceCountsErrorMockOperatorManager) DeleteResourceCollection(ctx context.Context) error {
-	return nil
-}
-
-type DeleteResourceCollectionErrorMockOperatorManager struct{}
-
-func NewDeleteResourceCollectionErrorMockOperatorManager() *DeleteResourceCollectionErrorMockOperatorManager {
-	return &DeleteResourceCollectionErrorMockOperatorManager{}
+// DeleteResourceCollection indicates an expected call of DeleteResourceCollection.
+func (mr *MockIOperatorManagerMockRecorder) DeleteResourceCollection(ctx interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteResourceCollection", reflect.TypeOf((*MockIOperatorManager)(nil).DeleteResourceCollection), ctx)
 }
 
-func (m *DeleteResourceCollectionErrorMockOperatorManager) SetOperatorCollection(stackName *string, stackResourceSummaries []types.StackResourceSummary) {
+// GetLogicalResourceIds mocks base method.
+func (m *MockIOperatorManager) GetLogicalResourceIds() []string {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "GetLogicalResourceIds")
+	ret0, _ := ret[0].([]string)
+	return ret0
 }
 
-func (m *DeleteResourceCollectionErrorMockOperatorManager) CheckResourceCounts() error {
-	return nil
+// GetLogicalResourceIds indicates an expected call of GetLogicalResourceIds.
+func (mr *MockIOperatorManagerMockRecorder) GetLogicalResourceIds() *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLogicalResourceIds", reflect.TypeOf((*MockIOperatorManager)(nil).GetLogicalResourceIds))
 }
 
-func (m *DeleteResourceCollectionErrorMockOperatorManager) GetLogicalResourceIds() []string {
-	return []string{"logicalResourceId1", "logicalResourceId2"}
+// SetOperatorCollection mocks base method.
+func (m *MockIOperatorManager) SetOperatorCollection(stackName *string, stackResourceSummaries []types.StackResourceSummary) {
+	m.ctrl.T.Helper()
+	m.ctrl.Call(m, "SetOperatorCollection", stackName, stackResourceSummaries)
 }
 
-func (m *DeleteResourceCollectionErrorMockOperatorManager) DeleteResourceCollection(ctx context.Context) error {
-	return fmt.Errorf("DeleteResourceCollectionError")
+// SetOperatorCollection indicates an expected call of SetOperatorCollection.
+func (mr *MockIOperatorManagerMockRecorder) SetOperatorCollection(stackName, stackResourceSummaries interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetOperatorCollection", reflect.TypeOf((*MockIOperatorManager)(nil).SetOperatorCollection), stackName, stackResourceSummaries)
 }
diff --git a/internal/operation/operator_mock.go b/internal/operation/operator_mock.go
index 4f03a17..94c7002 100644
--- a/internal/operation/operator_mock.go
+++ b/internal/operation/operator_mock.go
@@ -1,132 +1,76 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: ./operator.go
+
+// Package operation is a generated GoMock package.
 package operation
 
 import (
-	"context"
-	"fmt"
+	context "context"
+	reflect "reflect"
 
-	"github.com/aws/aws-sdk-go-v2/service/cloudformation/types"
+	types "github.com/aws/aws-sdk-go-v2/service/cloudformation/types"
+	gomock "github.com/golang/mock/gomock"
 )
 
-/*
-	Mocks for each Operator
-*/
-
-var _ IOperator = (*MockCloudFormationStackOperator)(nil)
-var _ IOperator = (*ErrorMockCloudFormationStackOperator)(nil)
-var _ IOperator = (*MockS3BucketOperator)(nil)
-var _ IOperator = (*MockIamRoleOperator)(nil)
-var _ IOperator = (*MockEcrRepositoryOperator)(nil)
-var _ IOperator = (*MockBackupVaultOperator)(nil)
-var _ IOperator = (*MockCustomOperator)(nil)
-
-type MockCloudFormationStackOperator struct{}
-
-func NewMockCloudFormationStackOperator() *MockCloudFormationStackOperator {
-	return &MockCloudFormationStackOperator{}
-}
-
-func (m *MockCloudFormationStackOperator) AddResource(resource *types.StackResourceSummary) {}
-
-func (m *MockCloudFormationStackOperator) GetResourcesLength() int {
-	return 1
-}
-
-func (m *MockCloudFormationStackOperator) DeleteResources(ctx context.Context) error {
-	return nil
-}
-
-type ErrorMockCloudFormationStackOperator struct{}
-
-func NewErrorMockCloudFormationStackOperator() *ErrorMockCloudFormationStackOperator {
-	return &ErrorMockCloudFormationStackOperator{}
-}
-
-func (m *ErrorMockCloudFormationStackOperator) AddResource(resource *types.StackResourceSummary) {}
-
-func (m *ErrorMockCloudFormationStackOperator) GetResourcesLength() int {
-	return 1
+// MockIOperator is a mock of IOperator interface.
+type MockIOperator struct {
+	ctrl     *gomock.Controller
+	recorder *MockIOperatorMockRecorder
 }
 
-func (m *ErrorMockCloudFormationStackOperator) DeleteResources(ctx context.Context) error {
-	return fmt.Errorf("ErrorDeleteResources")
+// MockIOperatorMockRecorder is the mock recorder for MockIOperator.
+type MockIOperatorMockRecorder struct {
+	mock *MockIOperator
 }
 
-type MockS3BucketOperator struct{}
-
-func NewMockS3BucketOperator() *MockS3BucketOperator {
-	return &MockS3BucketOperator{}
+// NewMockIOperator creates a new mock instance.
+func NewMockIOperator(ctrl *gomock.Controller) *MockIOperator {
+	mock := &MockIOperator{ctrl: ctrl}
+	mock.recorder = &MockIOperatorMockRecorder{mock}
+	return mock
 }
 
-func (m *MockS3BucketOperator) AddResource(resource *types.StackResourceSummary) {}
-
-func (m *MockS3BucketOperator) GetResourcesLength() int {
-	return 1
+// EXPECT returns an object that allows the caller to indicate expected use.
+func (m *MockIOperator) EXPECT() *MockIOperatorMockRecorder {
+	return m.recorder
 }
 
-func (m *MockS3BucketOperator) DeleteResources(ctx context.Context) error {
-	return nil
+// AddResource mocks base method.
+func (m *MockIOperator) AddResource(resource *types.StackResourceSummary) {
+	m.ctrl.T.Helper()
+	m.ctrl.Call(m, "AddResource", resource)
 }
 
-type MockIamRoleOperator struct{}
-
-func NewMockIamRoleOperator() *MockIamRoleOperator {
-	return &MockIamRoleOperator{}
+// AddResource indicates an expected call of AddResource.
+func (mr *MockIOperatorMockRecorder) AddResource(resource interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddResource", reflect.TypeOf((*MockIOperator)(nil).AddResource), resource)
 }
 
-func (m *MockIamRoleOperator) AddResource(resource *types.StackResourceSummary) {}
-
-func (m *MockIamRoleOperator) GetResourcesLength() int {
-	return 1
+// DeleteResources mocks base method.
+func (m *MockIOperator) DeleteResources(ctx context.Context) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DeleteResources", ctx)
+	ret0, _ := ret[0].(error)
+	return ret0
 }
 
-func (m *MockIamRoleOperator) DeleteResources(ctx context.Context) error {
-	return nil
+// DeleteResources indicates an expected call of DeleteResources.
+func (mr *MockIOperatorMockRecorder) DeleteResources(ctx interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteResources", reflect.TypeOf((*MockIOperator)(nil).DeleteResources), ctx)
 }
 
-type MockEcrRepositoryOperator struct{}
-
-func NewMockEcrRepositoryOperator() *MockEcrRepositoryOperator {
-	return &MockEcrRepositoryOperator{}
-}
-
-func (m *MockEcrRepositoryOperator) AddResource(resource *types.StackResourceSummary) {}
-
-func (m *MockEcrRepositoryOperator) GetResourcesLength() int {
-	return 1
-}
-
-func (m *MockEcrRepositoryOperator) DeleteResources(ctx context.Context) error {
-	return nil
-}
-
-type MockBackupVaultOperator struct{}
-
-func NewMockBackupVaultOperator() *MockBackupVaultOperator {
-	return &MockBackupVaultOperator{}
-}
-
-func (m *MockBackupVaultOperator) AddResource(resource *types.StackResourceSummary) {}
-
-func (m *MockBackupVaultOperator) GetResourcesLength() int {
-	return 1
-}
-
-func (m *MockBackupVaultOperator) DeleteResources(ctx context.Context) error {
-	return nil
-}
-
-type MockCustomOperator struct{}
-
-func NewMockCustomOperator() *MockCustomOperator {
-	return &MockCustomOperator{}
-}
-
-func (m *MockCustomOperator) AddResource(resource *types.StackResourceSummary) {}
-
-func (m *MockCustomOperator) GetResourcesLength() int {
-	return 1
+// GetResourcesLength mocks base method.
+func (m *MockIOperator) GetResourcesLength() int {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "GetResourcesLength")
+	ret0, _ := ret[0].(int)
+	return ret0
 }
 
-func (m *MockCustomOperator) DeleteResources(ctx context.Context) error {
-	return nil
+// GetResourcesLength indicates an expected call of GetResourcesLength.
+func (mr *MockIOperatorMockRecorder) GetResourcesLength() *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetResourcesLength", reflect.TypeOf((*MockIOperator)(nil).GetResourcesLength))
 }
diff --git a/pkg/client/backup.go b/pkg/client/backup.go
index c379ea8..444a263 100644
--- a/pkg/client/backup.go
+++ b/pkg/client/backup.go
@@ -1,3 +1,4 @@
+//go:generate mockgen -source=./backup.go -destination=./backup_mock.go -package=client
 package client
 
 import (
diff --git a/pkg/client/backup_mock.go b/pkg/client/backup_mock.go
index 90d8819..b2886bc 100644
--- a/pkg/client/backup_mock.go
+++ b/pkg/client/backup_mock.go
@@ -1,281 +1,108 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: ./backup.go
+
+// Package client is a generated GoMock package.
 package client
 
 import (
-	"context"
-	"fmt"
+	context "context"
+	reflect "reflect"
 
-	"github.com/aws/aws-sdk-go-v2/aws"
-	"github.com/aws/aws-sdk-go-v2/service/backup/types"
+	types "github.com/aws/aws-sdk-go-v2/service/backup/types"
+	gomock "github.com/golang/mock/gomock"
 )
 
-/*
-	Mocks for client
-*/
-
-var _ IBackup = (*MockBackup)(nil)
-var _ IBackup = (*AllErrorMockBackup)(nil)
-var _ IBackup = (*ListRecoveryPointsErrorMockBackup)(nil)
-var _ IBackup = (*DeleteRecoveryPointsErrorMockBackup)(nil)
-var _ IBackup = (*DeleteRecoveryPointsErrorAfterZeroLengthMockBackup)(nil)
-var _ IBackup = (*DeleteBackupVaultErrorMockBackup)(nil)
-var _ IBackup = (*CheckBackupVaultExistsErrorMockBackup)(nil)
-var _ IBackup = (*CheckBackupVaultNotExistsMockBackup)(nil)
-
-type MockBackup struct{}
-
-func NewMockBackup() *MockBackup {
-	return &MockBackup{}
-}
-
-func (m *MockBackup) ListRecoveryPointsByBackupVault(ctx context.Context, backupVaultName *string) ([]types.RecoveryPointByBackupVault, error) {
-	output := []types.RecoveryPointByBackupVault{
-		{
-			BackupVaultName: aws.String("BackupVaultName1"),
-			BackupVaultArn:  aws.String("BackupVaultArn1"),
-		},
-		{
-			BackupVaultName: aws.String("BackupVaultName2"),
-			BackupVaultArn:  aws.String("BackupVaultArn2"),
-		},
-	}
-	return output, nil
-}
-
-func (m *MockBackup) DeleteRecoveryPoints(ctx context.Context, backupVaultName *string, recoveryPoints []types.RecoveryPointByBackupVault) error {
-	return nil
-}
-
-func (m *MockBackup) DeleteRecoveryPoint(ctx context.Context, backupVaultName *string, recoveryPointArn *string) error {
-	return nil
-}
-
-func (m *MockBackup) DeleteBackupVault(ctx context.Context, backupVaultName *string) error {
-	return nil
-}
-
-func (m *MockBackup) CheckBackupVaultExists(ctx context.Context, backupVaultName *string) (bool, error) {
-	return true, nil
-}
-
-type AllErrorMockBackup struct{}
-
-func NewAllErrorMockBackup() *AllErrorMockBackup {
-	return &AllErrorMockBackup{}
-}
-
-func (m *AllErrorMockBackup) ListRecoveryPointsByBackupVault(ctx context.Context, backupVaultName *string) ([]types.RecoveryPointByBackupVault, error) {
-	return nil, fmt.Errorf("ListRecoveryPointsByBackupVaultError")
-}
-
-func (m *AllErrorMockBackup) DeleteRecoveryPoints(ctx context.Context, backupVaultName *string, recoveryPoints []types.RecoveryPointByBackupVault) error {
-	return fmt.Errorf("DeleteRecoveryPointsError")
-}
-
-func (m *AllErrorMockBackup) DeleteRecoveryPoint(ctx context.Context, backupVaultName *string, recoveryPointArn *string) error {
-	return fmt.Errorf("DeleteRecoveryPointError")
-}
-
-func (m *AllErrorMockBackup) DeleteBackupVault(ctx context.Context, backupVaultName *string) error {
-	return fmt.Errorf("DeleteBackupVaultError")
-}
-
-func (m *AllErrorMockBackup) CheckBackupVaultExists(ctx context.Context, backupVaultName *string) (bool, error) {
-	return false, fmt.Errorf("ListBackupVaultsError")
-}
-
-type ListRecoveryPointsErrorMockBackup struct{}
-
-func NewListRecoveryPointsErrorMockBackup() *ListRecoveryPointsErrorMockBackup {
-	return &ListRecoveryPointsErrorMockBackup{}
+// MockIBackup is a mock of IBackup interface.
+type MockIBackup struct {
+	ctrl     *gomock.Controller
+	recorder *MockIBackupMockRecorder
 }
 
-func (m *ListRecoveryPointsErrorMockBackup) ListRecoveryPointsByBackupVault(ctx context.Context, backupVaultName *string) ([]types.RecoveryPointByBackupVault, error) {
-	return nil, fmt.Errorf("ListRecoveryPointsByBackupVaultError")
+// MockIBackupMockRecorder is the mock recorder for MockIBackup.
+type MockIBackupMockRecorder struct {
+	mock *MockIBackup
 }
 
-func (m *ListRecoveryPointsErrorMockBackup) DeleteRecoveryPoints(ctx context.Context, backupVaultName *string, recoveryPoints []types.RecoveryPointByBackupVault) error {
-	return nil
+// NewMockIBackup creates a new mock instance.
+func NewMockIBackup(ctrl *gomock.Controller) *MockIBackup {
+	mock := &MockIBackup{ctrl: ctrl}
+	mock.recorder = &MockIBackupMockRecorder{mock}
+	return mock
 }
 
-func (m *ListRecoveryPointsErrorMockBackup) DeleteRecoveryPoint(ctx context.Context, backupVaultName *string, recoveryPointArn *string) error {
-	return nil
+// EXPECT returns an object that allows the caller to indicate expected use.
+func (m *MockIBackup) EXPECT() *MockIBackupMockRecorder {
+	return m.recorder
 }
 
-func (m *ListRecoveryPointsErrorMockBackup) DeleteBackupVault(ctx context.Context, backupVaultName *string) error {
-	return nil
+// CheckBackupVaultExists mocks base method.
+func (m *MockIBackup) CheckBackupVaultExists(ctx context.Context, backupVaultName *string) (bool, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "CheckBackupVaultExists", ctx, backupVaultName)
+	ret0, _ := ret[0].(bool)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
 }
 
-func (m *ListRecoveryPointsErrorMockBackup) CheckBackupVaultExists(ctx context.Context, backupVaultName *string) (bool, error) {
-	return true, nil
+// CheckBackupVaultExists indicates an expected call of CheckBackupVaultExists.
+func (mr *MockIBackupMockRecorder) CheckBackupVaultExists(ctx, backupVaultName interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckBackupVaultExists", reflect.TypeOf((*MockIBackup)(nil).CheckBackupVaultExists), ctx, backupVaultName)
 }
 
-type DeleteRecoveryPointsErrorMockBackup struct{}
-
-func NewDeleteRecoveryPointsErrorMockBackup() *DeleteRecoveryPointsErrorMockBackup {
-	return &DeleteRecoveryPointsErrorMockBackup{}
-}
-
-func (m *DeleteRecoveryPointsErrorMockBackup) ListRecoveryPointsByBackupVault(ctx context.Context, backupVaultName *string) ([]types.RecoveryPointByBackupVault, error) {
-	output := []types.RecoveryPointByBackupVault{
-		{
-			BackupVaultName: aws.String("BackupVaultName1"),
-			BackupVaultArn:  aws.String("BackupVaultArn1"),
-		},
-		{
-			BackupVaultName: aws.String("BackupVaultName2"),
-			BackupVaultArn:  aws.String("BackupVaultArn2"),
-		},
-	}
-	return output, nil
-}
-
-func (m *DeleteRecoveryPointsErrorMockBackup) DeleteRecoveryPoints(ctx context.Context, backupVaultName *string, recoveryPoints []types.RecoveryPointByBackupVault) error {
-	return fmt.Errorf("DeleteRecoveryPointsError")
+// DeleteBackupVault mocks base method.
+func (m *MockIBackup) DeleteBackupVault(ctx context.Context, backupVaultName *string) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DeleteBackupVault", ctx, backupVaultName)
+	ret0, _ := ret[0].(error)
+	return ret0
 }
 
-func (m *DeleteRecoveryPointsErrorMockBackup) DeleteRecoveryPoint(ctx context.Context, backupVaultName *string, recoveryPointArn *string) error {
-	return nil
+// DeleteBackupVault indicates an expected call of DeleteBackupVault.
+func (mr *MockIBackupMockRecorder) DeleteBackupVault(ctx, backupVaultName interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteBackupVault", reflect.TypeOf((*MockIBackup)(nil).DeleteBackupVault), ctx, backupVaultName)
 }
 
-func (m *DeleteRecoveryPointsErrorMockBackup) DeleteBackupVault(ctx context.Context, backupVaultName *string) error {
-	return nil
-}
-
-func (m *DeleteRecoveryPointsErrorMockBackup) CheckBackupVaultExists(ctx context.Context, backupVaultName *string) (bool, error) {
-	return true, nil
-}
-
-type DeleteRecoveryPointsErrorAfterZeroLengthMockBackup struct{}
-
-func NewDeleteRecoveryPointsErrorAfterZeroLengthMockBackup() *DeleteRecoveryPointsErrorAfterZeroLengthMockBackup {
-	return &DeleteRecoveryPointsErrorAfterZeroLengthMockBackup{}
-}
-
-func (m *DeleteRecoveryPointsErrorAfterZeroLengthMockBackup) ListRecoveryPointsByBackupVault(ctx context.Context, backupVaultName *string) ([]types.RecoveryPointByBackupVault, error) {
-	output := []types.RecoveryPointByBackupVault{}
-	return output, nil
-}
-
-func (m *DeleteRecoveryPointsErrorAfterZeroLengthMockBackup) DeleteRecoveryPoints(ctx context.Context, backupVaultName *string, recoveryPoints []types.RecoveryPointByBackupVault) error {
-	return fmt.Errorf("DeleteRecoveryPointsErrorAfterZeroLength")
-}
-
-func (m *DeleteRecoveryPointsErrorAfterZeroLengthMockBackup) DeleteRecoveryPoint(ctx context.Context, backupVaultName *string, recoveryPointArn *string) error {
-	return nil
-}
-
-func (m *DeleteRecoveryPointsErrorAfterZeroLengthMockBackup) DeleteBackupVault(ctx context.Context, backupVaultName *string) error {
-	return nil
-}
-
-func (m *DeleteRecoveryPointsErrorAfterZeroLengthMockBackup) CheckBackupVaultExists(ctx context.Context, backupVaultName *string) (bool, error) {
-	return true, nil
-}
-
-type DeleteBackupVaultErrorMockBackup struct{}
-
-func NewDeleteBackupVaultErrorMockBackup() *DeleteBackupVaultErrorMockBackup {
-	return &DeleteBackupVaultErrorMockBackup{}
-}
-
-func (m *DeleteBackupVaultErrorMockBackup) ListRecoveryPointsByBackupVault(ctx context.Context, backupVaultName *string) ([]types.RecoveryPointByBackupVault, error) {
-	output := []types.RecoveryPointByBackupVault{
-		{
-			BackupVaultName: aws.String("BackupVaultName1"),
-			BackupVaultArn:  aws.String("BackupVaultArn1"),
-		},
-		{
-			BackupVaultName: aws.String("BackupVaultName2"),
-			BackupVaultArn:  aws.String("BackupVaultArn2"),
-		},
-	}
-	return output, nil
-}
-
-func (m *DeleteBackupVaultErrorMockBackup) DeleteRecoveryPoints(ctx context.Context, backupVaultName *string, recoveryPoints []types.RecoveryPointByBackupVault) error {
-	return nil
-}
-
-func (m *DeleteBackupVaultErrorMockBackup) DeleteRecoveryPoint(ctx context.Context, backupVaultName *string, recoveryPointArn *string) error {
-	return nil
-}
-
-func (m *DeleteBackupVaultErrorMockBackup) DeleteBackupVault(ctx context.Context, backupVaultName *string) error {
-	return fmt.Errorf("DeleteBackupVaultError")
-}
-
-func (m *DeleteBackupVaultErrorMockBackup) CheckBackupVaultExists(ctx context.Context, backupVaultName *string) (bool, error) {
-	return true, nil
-}
-
-type CheckBackupVaultExistsErrorMockBackup struct{}
-
-func NewCheckBackupVaultExistsErrorMockBackup() *CheckBackupVaultExistsErrorMockBackup {
-	return &CheckBackupVaultExistsErrorMockBackup{}
-}
-
-func (m *CheckBackupVaultExistsErrorMockBackup) ListRecoveryPointsByBackupVault(ctx context.Context, backupVaultName *string) ([]types.RecoveryPointByBackupVault, error) {
-	output := []types.RecoveryPointByBackupVault{
-		{
-			BackupVaultName: aws.String("BackupVaultName1"),
-			BackupVaultArn:  aws.String("BackupVaultArn1"),
-		},
-		{
-			BackupVaultName: aws.String("BackupVaultName2"),
-			BackupVaultArn:  aws.String("BackupVaultArn2"),
-		},
-	}
-	return output, nil
-}
-
-func (m *CheckBackupVaultExistsErrorMockBackup) DeleteRecoveryPoints(ctx context.Context, backupVaultName *string, recoveryPoints []types.RecoveryPointByBackupVault) error {
-	return nil
-}
-
-func (m *CheckBackupVaultExistsErrorMockBackup) DeleteRecoveryPoint(ctx context.Context, backupVaultName *string, recoveryPointArn *string) error {
-	return nil
-}
-
-func (m *CheckBackupVaultExistsErrorMockBackup) DeleteBackupVault(ctx context.Context, backupVaultName *string) error {
-	return nil
-}
-
-func (m *CheckBackupVaultExistsErrorMockBackup) CheckBackupVaultExists(ctx context.Context, backupVaultName *string) (bool, error) {
-	return false, fmt.Errorf("ListBackupVaultsError")
-}
-
-type CheckBackupVaultNotExistsMockBackup struct{}
-
-func NewCheckBackupVaultNotExistsMockBackup() *CheckBackupVaultNotExistsMockBackup {
-	return &CheckBackupVaultNotExistsMockBackup{}
+// DeleteRecoveryPoint mocks base method.
+func (m *MockIBackup) DeleteRecoveryPoint(ctx context.Context, backupVaultName, recoveryPointArn *string) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DeleteRecoveryPoint", ctx, backupVaultName, recoveryPointArn)
+	ret0, _ := ret[0].(error)
+	return ret0
 }
 
-func (m *CheckBackupVaultNotExistsMockBackup) ListRecoveryPointsByBackupVault(ctx context.Context, backupVaultName *string) ([]types.RecoveryPointByBackupVault, error) {
-	output := []types.RecoveryPointByBackupVault{
-		{
-			BackupVaultName: aws.String("BackupVaultName1"),
-			BackupVaultArn:  aws.String("BackupVaultArn1"),
-		},
-		{
-			BackupVaultName: aws.String("BackupVaultName2"),
-			BackupVaultArn:  aws.String("BackupVaultArn2"),
-		},
-	}
-	return output, nil
+// DeleteRecoveryPoint indicates an expected call of DeleteRecoveryPoint.
+func (mr *MockIBackupMockRecorder) DeleteRecoveryPoint(ctx, backupVaultName, recoveryPointArn interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteRecoveryPoint", reflect.TypeOf((*MockIBackup)(nil).DeleteRecoveryPoint), ctx, backupVaultName, recoveryPointArn)
 }
 
-func (m *CheckBackupVaultNotExistsMockBackup) DeleteRecoveryPoints(ctx context.Context, backupVaultName *string, recoveryPoints []types.RecoveryPointByBackupVault) error {
-	return nil
+// DeleteRecoveryPoints mocks base method.
+func (m *MockIBackup) DeleteRecoveryPoints(ctx context.Context, backupVaultName *string, recoveryPoints []types.RecoveryPointByBackupVault) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DeleteRecoveryPoints", ctx, backupVaultName, recoveryPoints)
+	ret0, _ := ret[0].(error)
+	return ret0
 }
 
-func (m *CheckBackupVaultNotExistsMockBackup) DeleteRecoveryPoint(ctx context.Context, backupVaultName *string, recoveryPointArn *string) error {
-	return nil
+// DeleteRecoveryPoints indicates an expected call of DeleteRecoveryPoints.
+func (mr *MockIBackupMockRecorder) DeleteRecoveryPoints(ctx, backupVaultName, recoveryPoints interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteRecoveryPoints", reflect.TypeOf((*MockIBackup)(nil).DeleteRecoveryPoints), ctx, backupVaultName, recoveryPoints)
 }
 
-func (m *CheckBackupVaultNotExistsMockBackup) DeleteBackupVault(ctx context.Context, backupVaultName *string) error {
-	return nil
+// ListRecoveryPointsByBackupVault mocks base method.
+func (m *MockIBackup) ListRecoveryPointsByBackupVault(ctx context.Context, backupVaultName *string) ([]types.RecoveryPointByBackupVault, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "ListRecoveryPointsByBackupVault", ctx, backupVaultName)
+	ret0, _ := ret[0].([]types.RecoveryPointByBackupVault)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
 }
 
-func (m *CheckBackupVaultNotExistsMockBackup) CheckBackupVaultExists(ctx context.Context, backupVaultName *string) (bool, error) {
-	return false, nil
+// ListRecoveryPointsByBackupVault indicates an expected call of ListRecoveryPointsByBackupVault.
+func (mr *MockIBackupMockRecorder) ListRecoveryPointsByBackupVault(ctx, backupVaultName interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListRecoveryPointsByBackupVault", reflect.TypeOf((*MockIBackup)(nil).ListRecoveryPointsByBackupVault), ctx, backupVaultName)
 }
diff --git a/pkg/client/cloudformation.go b/pkg/client/cloudformation.go
index 7ef054b..9e1df3e 100644
--- a/pkg/client/cloudformation.go
+++ b/pkg/client/cloudformation.go
@@ -1,3 +1,4 @@
+//go:generate mockgen -source=./cloudformation.go -destination=./cloudformation_mock.go -package=client
 package client
 
 import (
diff --git a/pkg/client/cloudformation_mock.go b/pkg/client/cloudformation_mock.go
index 917c957..e825901 100644
--- a/pkg/client/cloudformation_mock.go
+++ b/pkg/client/cloudformation_mock.go
@@ -1,518 +1,97 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: ./cloudformation.go
+
+// Package client is a generated GoMock package.
 package client
 
 import (
-	"context"
-	"fmt"
+	context "context"
+	reflect "reflect"
 
-	"github.com/aws/aws-sdk-go-v2/aws"
-	"github.com/aws/aws-sdk-go-v2/service/cloudformation"
-	"github.com/aws/aws-sdk-go-v2/service/cloudformation/types"
+	cloudformation "github.com/aws/aws-sdk-go-v2/service/cloudformation"
+	types "github.com/aws/aws-sdk-go-v2/service/cloudformation/types"
+	gomock "github.com/golang/mock/gomock"
 )
 
-/*
-	Mocks for client
-*/
-
-var _ ICloudFormation = (*MockCloudFormation)(nil)
-var _ ICloudFormation = (*TerminationProtectionIsEnabledMockCloudFormation)(nil)
-var _ ICloudFormation = (*NotDeleteFailedMockCloudFormation)(nil)
-var _ ICloudFormation = (*AllErrorMockCloudFormation)(nil)
-var _ ICloudFormation = (*DeleteStackErrorMockCloudFormation)(nil)
-var _ ICloudFormation = (*DescribeStacksErrorMockCloudFormation)(nil)
-var _ ICloudFormation = (*DescribeStacksNotExistsErrorMockCloudFormation)(nil)
-var _ ICloudFormation = (*ListStackResourcesErrorMockCloudFormation)(nil)
-var _ ICloudFormation = (*ListStacksErrorMockCloudFormation)(nil)
-var _ ICloudFormation = (*ListStacksEmptyMockCloudFormation)(nil)
-
-type MockCloudFormation struct{}
-
-func NewMockCloudFormation() *MockCloudFormation {
-	return &MockCloudFormation{}
-}
-
-func (m *MockCloudFormation) DeleteStack(ctx context.Context, stackName *string, retainResources []string) error {
-	return nil
-}
-
-func (m *MockCloudFormation) DescribeStacks(ctx context.Context, stackName *string) (*cloudformation.DescribeStacksOutput, bool, error) {
-	output := &cloudformation.DescribeStacksOutput{
-		Stacks: []types.Stack{
-			{
-				StackName:                   aws.String("StackName"),
-				StackStatus:                 "DELETE_FAILED",
-				EnableTerminationProtection: aws.Bool(false),
-			},
-		},
-	}
-	return output, true, nil
-}
-
-func (m *MockCloudFormation) ListStackResources(ctx context.Context, stackName *string) ([]types.StackResourceSummary, error) {
-	output := []types.StackResourceSummary{
-		{
-			LogicalResourceId:  aws.String("LogicalResourceId1"),
-			ResourceStatus:     "DELETE_FAILED",
-			ResourceType:       aws.String("AWS::CloudFormation::Stack"),
-			PhysicalResourceId: aws.String("PhysicalResourceId1"),
-		},
-		{
-			LogicalResourceId:  aws.String("LogicalResourceId2"),
-			ResourceStatus:     "DELETE_FAILED",
-			ResourceType:       aws.String("AWS::S3::Bucket"),
-			PhysicalResourceId: aws.String("PhysicalResourceId2"),
-		},
-	}
-
-	return output, nil
-}
-
-func (m *MockCloudFormation) ListStacks(ctx context.Context) ([]types.StackSummary, error) {
-	output := []types.StackSummary{
-		{
-			StackName:   aws.String("TestStack1"),
-			StackStatus: types.StackStatusCreateComplete,
-		},
-		{
-			StackName:   aws.String("TestStack2"),
-			StackStatus: types.StackStatusCreateComplete,
-		},
-	}
-
-	return output, nil
+// MockICloudFormation is a mock of ICloudFormation interface.
+type MockICloudFormation struct {
+	ctrl     *gomock.Controller
+	recorder *MockICloudFormationMockRecorder
 }
 
-type TerminationProtectionIsEnabledMockCloudFormation struct{}
-
-func NewTerminationProtectionIsEnabledMockCloudFormation() *TerminationProtectionIsEnabledMockCloudFormation {
-	return &TerminationProtectionIsEnabledMockCloudFormation{}
-}
-
-func (m *TerminationProtectionIsEnabledMockCloudFormation) DeleteStack(ctx context.Context, stackName *string, retainResources []string) error {
-	return nil
-}
-
-func (m *TerminationProtectionIsEnabledMockCloudFormation) DescribeStacks(ctx context.Context, stackName *string) (*cloudformation.DescribeStacksOutput, bool, error) {
-	output := &cloudformation.DescribeStacksOutput{
-		Stacks: []types.Stack{
-			{
-				StackName:                   aws.String("StackName"),
-				StackStatus:                 "CREATE_COMPLETE",
-				EnableTerminationProtection: aws.Bool(true),
-			},
-		},
-	}
-	return output, true, nil
-}
-
-func (m *TerminationProtectionIsEnabledMockCloudFormation) ListStackResources(ctx context.Context, stackName *string) ([]types.StackResourceSummary, error) {
-	output := []types.StackResourceSummary{
-		{
-			LogicalResourceId:  aws.String("LogicalResourceId1"),
-			ResourceStatus:     "DELETE_FAILED",
-			ResourceType:       aws.String("AWS::CloudFormation::Stack"),
-			PhysicalResourceId: aws.String("PhysicalResourceId1"),
-		},
-		{
-			LogicalResourceId:  aws.String("LogicalResourceId2"),
-			ResourceStatus:     "DELETE_FAILED",
-			ResourceType:       aws.String("AWS::S3::Bucket"),
-			PhysicalResourceId: aws.String("PhysicalResourceId2"),
-		},
-	}
-
-	return output, nil
+// MockICloudFormationMockRecorder is the mock recorder for MockICloudFormation.
+type MockICloudFormationMockRecorder struct {
+	mock *MockICloudFormation
 }
 
-func (m *TerminationProtectionIsEnabledMockCloudFormation) ListStacks(ctx context.Context) ([]types.StackSummary, error) {
-	output := []types.StackSummary{
-		{
-			StackName:   aws.String("TestStack1"),
-			StackStatus: types.StackStatusCreateComplete,
-		},
-		{
-			StackName:   aws.String("TestStack2"),
-			StackStatus: types.StackStatusCreateComplete,
-		},
-	}
-
-	return output, nil
+// NewMockICloudFormation creates a new mock instance.
+func NewMockICloudFormation(ctrl *gomock.Controller) *MockICloudFormation {
+	mock := &MockICloudFormation{ctrl: ctrl}
+	mock.recorder = &MockICloudFormationMockRecorder{mock}
+	return mock
 }
 
-type NotDeleteFailedMockCloudFormation struct{}
-
-func NewNotDeleteFailedMockCloudFormation() *NotDeleteFailedMockCloudFormation {
-	return &NotDeleteFailedMockCloudFormation{}
+// EXPECT returns an object that allows the caller to indicate expected use.
+func (m *MockICloudFormation) EXPECT() *MockICloudFormationMockRecorder {
+	return m.recorder
 }
 
-func (m *NotDeleteFailedMockCloudFormation) DeleteStack(ctx context.Context, stackName *string, retainResources []string) error {
-	return nil
+// DeleteStack mocks base method.
+func (m *MockICloudFormation) DeleteStack(ctx context.Context, stackName *string, retainResources []string) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DeleteStack", ctx, stackName, retainResources)
+	ret0, _ := ret[0].(error)
+	return ret0
 }
 
-func (m *NotDeleteFailedMockCloudFormation) DescribeStacks(ctx context.Context, stackName *string) (*cloudformation.DescribeStacksOutput, bool, error) {
-	output := &cloudformation.DescribeStacksOutput{
-		Stacks: []types.Stack{
-			{
-				StackName:                   aws.String("StackName"),
-				StackStatus:                 "UPDATE_ROLLBACK_COMPLETE",
-				EnableTerminationProtection: aws.Bool(false),
-			},
-		},
-	}
-	return output, true, nil
+// DeleteStack indicates an expected call of DeleteStack.
+func (mr *MockICloudFormationMockRecorder) DeleteStack(ctx, stackName, retainResources interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteStack", reflect.TypeOf((*MockICloudFormation)(nil).DeleteStack), ctx, stackName, retainResources)
 }
 
-func (m *NotDeleteFailedMockCloudFormation) ListStackResources(ctx context.Context, stackName *string) ([]types.StackResourceSummary, error) {
-	output := []types.StackResourceSummary{
-		{
-			LogicalResourceId:  aws.String("LogicalResourceId1"),
-			ResourceStatus:     "UPDATE_ROLLBACK_COMPLETE",
-			ResourceType:       aws.String("AWS::CloudFormation::Stack"),
-			PhysicalResourceId: aws.String("PhysicalResourceId1"),
-		},
-		{
-			LogicalResourceId:  aws.String("LogicalResourceId2"),
-			ResourceStatus:     "UPDATE_ROLLBACK_COMPLETE",
-			ResourceType:       aws.String("AWS::S3::Bucket"),
-			PhysicalResourceId: aws.String("PhysicalResourceId2"),
-		},
-	}
-
-	return output, nil
+// DescribeStacks mocks base method.
+func (m *MockICloudFormation) DescribeStacks(ctx context.Context, stackName *string) (*cloudformation.DescribeStacksOutput, bool, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DescribeStacks", ctx, stackName)
+	ret0, _ := ret[0].(*cloudformation.DescribeStacksOutput)
+	ret1, _ := ret[1].(bool)
+	ret2, _ := ret[2].(error)
+	return ret0, ret1, ret2
 }
 
-func (m *NotDeleteFailedMockCloudFormation) ListStacks(ctx context.Context) ([]types.StackSummary, error) {
-	output := []types.StackSummary{
-		{
-			StackName:   aws.String("TestStack1"),
-			StackStatus: types.StackStatusCreateComplete,
-		},
-		{
-			StackName:   aws.String("TestStack2"),
-			StackStatus: types.StackStatusCreateComplete,
-		},
-	}
-
-	return output, nil
+// DescribeStacks indicates an expected call of DescribeStacks.
+func (mr *MockICloudFormationMockRecorder) DescribeStacks(ctx, stackName interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DescribeStacks", reflect.TypeOf((*MockICloudFormation)(nil).DescribeStacks), ctx, stackName)
 }
 
-type AllErrorMockCloudFormation struct{}
-
-func NewAllErrorMockCloudFormation() *AllErrorMockCloudFormation {
-	return &AllErrorMockCloudFormation{}
+// ListStackResources mocks base method.
+func (m *MockICloudFormation) ListStackResources(ctx context.Context, stackName *string) ([]types.StackResourceSummary, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "ListStackResources", ctx, stackName)
+	ret0, _ := ret[0].([]types.StackResourceSummary)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
 }
 
-func (m *AllErrorMockCloudFormation) DeleteStack(ctx context.Context, stackName *string, retainResources []string) error {
-	return fmt.Errorf("DeleteStackError")
+// ListStackResources indicates an expected call of ListStackResources.
+func (mr *MockICloudFormationMockRecorder) ListStackResources(ctx, stackName interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListStackResources", reflect.TypeOf((*MockICloudFormation)(nil).ListStackResources), ctx, stackName)
 }
 
-func (m *AllErrorMockCloudFormation) DescribeStacks(ctx context.Context, stackName *string) (*cloudformation.DescribeStacksOutput, bool, error) {
-	output := &cloudformation.DescribeStacksOutput{}
-	return output, true, fmt.Errorf("DescribeStacksError")
+// ListStacks mocks base method.
+func (m *MockICloudFormation) ListStacks(ctx context.Context) ([]types.StackSummary, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "ListStacks", ctx)
+	ret0, _ := ret[0].([]types.StackSummary)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
 }
 
-func (m *AllErrorMockCloudFormation) ListStackResources(ctx context.Context, stackName *string) ([]types.StackResourceSummary, error) {
-	output := []types.StackResourceSummary{}
-
-	return output, fmt.Errorf("ListStackResourcesError")
-}
-
-func (m *AllErrorMockCloudFormation) ListStacks(ctx context.Context) ([]types.StackSummary, error) {
-	output := []types.StackSummary{}
-
-	return output, fmt.Errorf("ListStacksError")
-}
-
-type DeleteStackErrorMockCloudFormation struct{}
-
-func NewDeleteStackErrorMockCloudFormation() *DeleteStackErrorMockCloudFormation {
-	return &DeleteStackErrorMockCloudFormation{}
-}
-
-func (m *DeleteStackErrorMockCloudFormation) DeleteStack(ctx context.Context, stackName *string, retainResources []string) error {
-	return fmt.Errorf("DeleteStackError")
-}
-
-func (m *DeleteStackErrorMockCloudFormation) DescribeStacks(ctx context.Context, stackName *string) (*cloudformation.DescribeStacksOutput, bool, error) {
-	output := &cloudformation.DescribeStacksOutput{
-		Stacks: []types.Stack{
-			{
-				StackName:                   aws.String("StackName"),
-				StackStatus:                 "DELETE_FAILED",
-				EnableTerminationProtection: aws.Bool(false),
-			},
-		},
-	}
-	return output, true, nil
-}
-
-func (m *DeleteStackErrorMockCloudFormation) ListStackResources(ctx context.Context, stackName *string) ([]types.StackResourceSummary, error) {
-	output := []types.StackResourceSummary{
-		{
-			LogicalResourceId:  aws.String("LogicalResourceId1"),
-			ResourceStatus:     "DELETE_FAILED",
-			ResourceType:       aws.String("AWS::CloudFormation::Stack"),
-			PhysicalResourceId: aws.String("PhysicalResourceId1"),
-		},
-		{
-			LogicalResourceId:  aws.String("LogicalResourceId2"),
-			ResourceStatus:     "DELETE_FAILED",
-			ResourceType:       aws.String("AWS::S3::Bucket"),
-			PhysicalResourceId: aws.String("PhysicalResourceId2"),
-		},
-	}
-
-	return output, nil
-}
-
-func (m *DeleteStackErrorMockCloudFormation) ListStacks(ctx context.Context) ([]types.StackSummary, error) {
-	output := []types.StackSummary{
-		{
-			StackName:   aws.String("TestStack1"),
-			StackStatus: types.StackStatusCreateComplete,
-		},
-		{
-			StackName:   aws.String("TestStack2"),
-			StackStatus: types.StackStatusCreateComplete,
-		},
-	}
-
-	return output, nil
-}
-
-type DescribeStacksErrorMockCloudFormation struct{}
-
-func NewDescribeStacksErrorMockCloudFormation() *DescribeStacksErrorMockCloudFormation {
-	return &DescribeStacksErrorMockCloudFormation{}
-}
-
-func (m *DescribeStacksErrorMockCloudFormation) DeleteStack(ctx context.Context, stackName *string, retainResources []string) error {
-	return nil
-}
-
-func (m *DescribeStacksErrorMockCloudFormation) DescribeStacks(ctx context.Context, stackName *string) (*cloudformation.DescribeStacksOutput, bool, error) {
-	output := &cloudformation.DescribeStacksOutput{}
-	return output, true, fmt.Errorf("DescribeStacksError")
-}
-
-func (m *DescribeStacksErrorMockCloudFormation) ListStackResources(ctx context.Context, stackName *string) ([]types.StackResourceSummary, error) {
-	output := []types.StackResourceSummary{
-		{
-			LogicalResourceId:  aws.String("LogicalResourceId1"),
-			ResourceStatus:     "DELETE_FAILED",
-			ResourceType:       aws.String("AWS::CloudFormation::Stack"),
-			PhysicalResourceId: aws.String("PhysicalResourceId1"),
-		},
-		{
-			LogicalResourceId:  aws.String("LogicalResourceId2"),
-			ResourceStatus:     "DELETE_FAILED",
-			ResourceType:       aws.String("AWS::S3::Bucket"),
-			PhysicalResourceId: aws.String("PhysicalResourceId2"),
-		},
-	}
-
-	return output, nil
-}
-
-func (m *DescribeStacksErrorMockCloudFormation) ListStacks(ctx context.Context) ([]types.StackSummary, error) {
-	output := []types.StackSummary{
-		{
-			StackName:   aws.String("TestStack1"),
-			StackStatus: types.StackStatusCreateComplete,
-		},
-		{
-			StackName:   aws.String("TestStack2"),
-			StackStatus: types.StackStatusCreateComplete,
-		},
-	}
-
-	return output, nil
-}
-
-type DescribeStacksNotExistsErrorMockCloudFormation struct{}
-
-func NewDescribeStacksNotExistsErrorMockCloudFormation() *DescribeStacksNotExistsErrorMockCloudFormation {
-	return &DescribeStacksNotExistsErrorMockCloudFormation{}
-}
-
-func (m *DescribeStacksNotExistsErrorMockCloudFormation) DeleteStack(ctx context.Context, stackName *string, retainResources []string) error {
-	return nil
-}
-
-func (m *DescribeStacksNotExistsErrorMockCloudFormation) DescribeStacks(ctx context.Context, stackName *string) (*cloudformation.DescribeStacksOutput, bool, error) {
-	output := &cloudformation.DescribeStacksOutput{}
-	return output, false, nil
-}
-
-func (m *DescribeStacksNotExistsErrorMockCloudFormation) ListStackResources(ctx context.Context, stackName *string) ([]types.StackResourceSummary, error) {
-	output := []types.StackResourceSummary{
-		{
-			LogicalResourceId:  aws.String("LogicalResourceId1"),
-			ResourceStatus:     "DELETE_FAILED",
-			ResourceType:       aws.String("AWS::CloudFormation::Stack"),
-			PhysicalResourceId: aws.String("PhysicalResourceId1"),
-		},
-		{
-			LogicalResourceId:  aws.String("LogicalResourceId2"),
-			ResourceStatus:     "DELETE_FAILED",
-			ResourceType:       aws.String("AWS::S3::Bucket"),
-			PhysicalResourceId: aws.String("PhysicalResourceId2"),
-		},
-	}
-
-	return output, nil
-}
-
-func (m *DescribeStacksNotExistsErrorMockCloudFormation) ListStacks(ctx context.Context) ([]types.StackSummary, error) {
-	output := []types.StackSummary{
-		{
-			StackName:   aws.String("TestStack1"),
-			StackStatus: types.StackStatusCreateComplete,
-		},
-		{
-			StackName:   aws.String("TestStack2"),
-			StackStatus: types.StackStatusCreateComplete,
-		},
-	}
-
-	return output, nil
-}
-
-type ListStackResourcesErrorMockCloudFormation struct{}
-
-func NewListStackResourcesErrorMockCloudFormation() *ListStackResourcesErrorMockCloudFormation {
-	return &ListStackResourcesErrorMockCloudFormation{}
-}
-
-func (m *ListStackResourcesErrorMockCloudFormation) DeleteStack(ctx context.Context, stackName *string, retainResources []string) error {
-	return nil
-}
-
-func (m *ListStackResourcesErrorMockCloudFormation) DescribeStacks(ctx context.Context, stackName *string) (*cloudformation.DescribeStacksOutput, bool, error) {
-	output := &cloudformation.DescribeStacksOutput{
-		Stacks: []types.Stack{
-			{
-				StackName:                   aws.String("StackName"),
-				StackStatus:                 "DELETE_FAILED",
-				EnableTerminationProtection: aws.Bool(false),
-			},
-		},
-	}
-	return output, true, nil
-}
-
-func (m *ListStackResourcesErrorMockCloudFormation) ListStackResources(ctx context.Context, stackName *string) ([]types.StackResourceSummary, error) {
-	output := []types.StackResourceSummary{}
-
-	return output, fmt.Errorf("ListStackResourcesError")
-}
-
-func (m *ListStackResourcesErrorMockCloudFormation) ListStacks(ctx context.Context) ([]types.StackSummary, error) {
-	output := []types.StackSummary{
-		{
-			StackName:   aws.String("TestStack1"),
-			StackStatus: types.StackStatusCreateComplete,
-		},
-		{
-			StackName:   aws.String("TestStack2"),
-			StackStatus: types.StackStatusCreateComplete,
-		},
-	}
-
-	return output, nil
-}
-
-type ListStacksErrorMockCloudFormation struct{}
-
-func NewListStacksErrorMockCloudFormation() *ListStacksErrorMockCloudFormation {
-	return &ListStacksErrorMockCloudFormation{}
-}
-
-func (m *ListStacksErrorMockCloudFormation) DeleteStack(ctx context.Context, stackName *string, retainResources []string) error {
-	return nil
-}
-
-func (m *ListStacksErrorMockCloudFormation) DescribeStacks(ctx context.Context, stackName *string) (*cloudformation.DescribeStacksOutput, bool, error) {
-	output := &cloudformation.DescribeStacksOutput{
-		Stacks: []types.Stack{
-			{
-				StackName:                   aws.String("StackName"),
-				StackStatus:                 "DELETE_FAILED",
-				EnableTerminationProtection: aws.Bool(false),
-			},
-		},
-	}
-	return output, true, nil
-}
-
-func (m *ListStacksErrorMockCloudFormation) ListStackResources(ctx context.Context, stackName *string) ([]types.StackResourceSummary, error) {
-	output := []types.StackResourceSummary{
-		{
-			LogicalResourceId:  aws.String("LogicalResourceId1"),
-			ResourceStatus:     "DELETE_FAILED",
-			ResourceType:       aws.String("AWS::CloudFormation::Stack"),
-			PhysicalResourceId: aws.String("PhysicalResourceId1"),
-		},
-		{
-			LogicalResourceId:  aws.String("LogicalResourceId2"),
-			ResourceStatus:     "DELETE_FAILED",
-			ResourceType:       aws.String("AWS::S3::Bucket"),
-			PhysicalResourceId: aws.String("PhysicalResourceId2"),
-		},
-	}
-
-	return output, nil
-}
-
-func (m *ListStacksErrorMockCloudFormation) ListStacks(ctx context.Context) ([]types.StackSummary, error) {
-	output := []types.StackSummary{}
-
-	return output, fmt.Errorf("ListStacksError")
-}
-
-type ListStacksEmptyMockCloudFormation struct{}
-
-func NewListStacksEmptyMockCloudFormation() *ListStacksEmptyMockCloudFormation {
-	return &ListStacksEmptyMockCloudFormation{}
-}
-
-func (m *ListStacksEmptyMockCloudFormation) DeleteStack(ctx context.Context, stackName *string, retainResources []string) error {
-	return nil
-}
-
-func (m *ListStacksEmptyMockCloudFormation) DescribeStacks(ctx context.Context, stackName *string) (*cloudformation.DescribeStacksOutput, bool, error) {
-	output := &cloudformation.DescribeStacksOutput{
-		Stacks: []types.Stack{
-			{
-				StackName:                   aws.String("StackName"),
-				StackStatus:                 "DELETE_FAILED",
-				EnableTerminationProtection: aws.Bool(false),
-			},
-		},
-	}
-	return output, true, nil
-}
-
-func (m *ListStacksEmptyMockCloudFormation) ListStackResources(ctx context.Context, stackName *string) ([]types.StackResourceSummary, error) {
-	output := []types.StackResourceSummary{
-		{
-			LogicalResourceId:  aws.String("LogicalResourceId1"),
-			ResourceStatus:     "DELETE_FAILED",
-			ResourceType:       aws.String("AWS::CloudFormation::Stack"),
-			PhysicalResourceId: aws.String("PhysicalResourceId1"),
-		},
-		{
-			LogicalResourceId:  aws.String("LogicalResourceId2"),
-			ResourceStatus:     "DELETE_FAILED",
-			ResourceType:       aws.String("AWS::S3::Bucket"),
-			PhysicalResourceId: aws.String("PhysicalResourceId2"),
-		},
-	}
-
-	return output, nil
-}
-
-func (m *ListStacksEmptyMockCloudFormation) ListStacks(ctx context.Context) ([]types.StackSummary, error) {
-	output := []types.StackSummary{}
-
-	return output, nil
+// ListStacks indicates an expected call of ListStacks.
+func (mr *MockICloudFormationMockRecorder) ListStacks(ctx interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListStacks", reflect.TypeOf((*MockICloudFormation)(nil).ListStacks), ctx)
 }
diff --git a/pkg/client/ecr.go b/pkg/client/ecr.go
index 06233f5..b300601 100644
--- a/pkg/client/ecr.go
+++ b/pkg/client/ecr.go
@@ -1,3 +1,4 @@
+//go:generate mockgen -source=./ecr.go -destination=./ecr_mock.go -package=client
 package client
 
 import (
diff --git a/pkg/client/ecr_mock.go b/pkg/client/ecr_mock.go
index 89bd3dd..29310a3 100644
--- a/pkg/client/ecr_mock.go
+++ b/pkg/client/ecr_mock.go
@@ -1,71 +1,64 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: ./ecr.go
+
+// Package client is a generated GoMock package.
 package client
 
 import (
-	"context"
-	"fmt"
-)
-
-/*
-	Mocks for client
-*/
-
-var _ IEcr = (*MockEcr)(nil)
-var _ IEcr = (*DeleteRepositoryErrorMockEcr)(nil)
-var _ IEcr = (*CheckEcrExistsErrorMockEcr)(nil)
-var _ IEcr = (*CheckEcrNotExistsMockEcr)(nil)
-
-type MockEcr struct{}
-
-func NewMockEcr() *MockEcr {
-	return &MockEcr{}
-}
-
-func (m *MockEcr) DeleteRepository(ctx context.Context, repositoryName *string) error {
-	return nil
-}
-
-func (m *MockEcr) CheckEcrExists(ctx context.Context, repositoryName *string) (bool, error) {
-	return true, nil
-}
-
-type DeleteRepositoryErrorMockEcr struct{}
+	context "context"
+	reflect "reflect"
 
-func NewDeleteRepositoryErrorMockEcr() *DeleteRepositoryErrorMockEcr {
-	return &DeleteRepositoryErrorMockEcr{}
-}
+	gomock "github.com/golang/mock/gomock"
+)
 
-func (m *DeleteRepositoryErrorMockEcr) DeleteRepository(ctx context.Context, repositoryName *string) error {
-	return fmt.Errorf("DeleteRepositoryError")
+// MockIEcr is a mock of IEcr interface.
+type MockIEcr struct {
+	ctrl     *gomock.Controller
+	recorder *MockIEcrMockRecorder
 }
 
-func (m *DeleteRepositoryErrorMockEcr) CheckEcrExists(ctx context.Context, repositoryName *string) (bool, error) {
-	return true, nil
+// MockIEcrMockRecorder is the mock recorder for MockIEcr.
+type MockIEcrMockRecorder struct {
+	mock *MockIEcr
 }
 
-type CheckEcrExistsErrorMockEcr struct{}
-
-func NewCheckEcrExistsErrorMockEcr() *CheckEcrExistsErrorMockEcr {
-	return &CheckEcrExistsErrorMockEcr{}
+// NewMockIEcr creates a new mock instance.
+func NewMockIEcr(ctrl *gomock.Controller) *MockIEcr {
+	mock := &MockIEcr{ctrl: ctrl}
+	mock.recorder = &MockIEcrMockRecorder{mock}
+	return mock
 }
 
-func (m *CheckEcrExistsErrorMockEcr) DeleteRepository(ctx context.Context, repositoryName *string) error {
-	return nil
+// EXPECT returns an object that allows the caller to indicate expected use.
+func (m *MockIEcr) EXPECT() *MockIEcrMockRecorder {
+	return m.recorder
 }
 
-func (m *CheckEcrExistsErrorMockEcr) CheckEcrExists(ctx context.Context, repositoryName *string) (bool, error) {
-	return false, fmt.Errorf("DescribeRepositoriesError")
+// CheckEcrExists mocks base method.
+func (m *MockIEcr) CheckEcrExists(ctx context.Context, repositoryName *string) (bool, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "CheckEcrExists", ctx, repositoryName)
+	ret0, _ := ret[0].(bool)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
 }
 
-type CheckEcrNotExistsMockEcr struct{}
-
-func NewCheckEcrNotExistsMockEcr() *CheckEcrNotExistsMockEcr {
-	return &CheckEcrNotExistsMockEcr{}
+// CheckEcrExists indicates an expected call of CheckEcrExists.
+func (mr *MockIEcrMockRecorder) CheckEcrExists(ctx, repositoryName interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckEcrExists", reflect.TypeOf((*MockIEcr)(nil).CheckEcrExists), ctx, repositoryName)
 }
 
-func (m *CheckEcrNotExistsMockEcr) DeleteRepository(ctx context.Context, repositoryName *string) error {
-	return nil
+// DeleteRepository mocks base method.
+func (m *MockIEcr) DeleteRepository(ctx context.Context, repositoryName *string) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DeleteRepository", ctx, repositoryName)
+	ret0, _ := ret[0].(error)
+	return ret0
 }
 
-func (m *CheckEcrNotExistsMockEcr) CheckEcrExists(ctx context.Context, repositoryName *string) (bool, error) {
-	return false, nil
+// DeleteRepository indicates an expected call of DeleteRepository.
+func (mr *MockIEcrMockRecorder) DeleteRepository(ctx, repositoryName interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteRepository", reflect.TypeOf((*MockIEcr)(nil).DeleteRepository), ctx, repositoryName)
 }
diff --git a/pkg/client/iam.go b/pkg/client/iam.go
index 47133c5..689c64d 100644
--- a/pkg/client/iam.go
+++ b/pkg/client/iam.go
@@ -1,3 +1,4 @@
+//go:generate mockgen -source=./iam.go -destination=./iam_mock.go -package=client
 package client
 
 import (
diff --git a/pkg/client/iam_mock.go b/pkg/client/iam_mock.go
index c0d3fbb..c853ab3 100644
--- a/pkg/client/iam_mock.go
+++ b/pkg/client/iam_mock.go
@@ -1,281 +1,108 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: ./iam.go
+
+// Package client is a generated GoMock package.
 package client
 
 import (
-	"context"
-	"fmt"
+	context "context"
+	reflect "reflect"
 
-	"github.com/aws/aws-sdk-go-v2/aws"
-	"github.com/aws/aws-sdk-go-v2/service/iam/types"
+	types "github.com/aws/aws-sdk-go-v2/service/iam/types"
+	gomock "github.com/golang/mock/gomock"
 )
 
-/*
-	Mocks for client
-*/
-
-var _ IIam = (*MockIam)(nil)
-var _ IIam = (*AllErrorMockIam)(nil)
-var _ IIam = (*DeleteRoleErrorMockIam)(nil)
-var _ IIam = (*ListAttachedRolePoliciesErrorMockIam)(nil)
-var _ IIam = (*DetachRolePoliciesErrorMockIam)(nil)
-var _ IIam = (*DetachRolePoliciesErrorAfterZeroLengthMockIam)(nil)
-var _ IIam = (*CheckRoleExistsErrorMockRole)(nil)
-var _ IIam = (*CheckRoleNotExistsMockRole)(nil)
-
-type MockIam struct{}
-
-func NewMockIam() *MockIam {
-	return &MockIam{}
-}
-
-func (m *MockIam) DeleteRole(ctx context.Context, roleName *string) error {
-	return nil
-}
-
-func (m *MockIam) ListAttachedRolePolicies(ctx context.Context, roleName *string) ([]types.AttachedPolicy, error) {
-	output := []types.AttachedPolicy{
-		{
-			PolicyArn:  aws.String("PolicyArn1"),
-			PolicyName: aws.String("PolicyName1"),
-		},
-		{
-			PolicyArn:  aws.String("PolicyArn2"),
-			PolicyName: aws.String("PolicyName2"),
-		},
-	}
-	return output, nil
-}
-
-func (m *MockIam) DetachRolePolicies(ctx context.Context, roleName *string, policies []types.AttachedPolicy) error {
-	return nil
-}
-
-func (m *MockIam) DetachRolePolicy(ctx context.Context, roleName *string, PolicyArn *string) error {
-	return nil
-}
-
-func (m *MockIam) CheckRoleExists(ctx context.Context, repositoryName *string) (bool, error) {
-	return true, nil
-}
-
-type AllErrorMockIam struct{}
-
-func NewAllErrorMockIam() *AllErrorMockIam {
-	return &AllErrorMockIam{}
-}
-
-func (m *AllErrorMockIam) DeleteRole(ctx context.Context, roleName *string) error {
-	return fmt.Errorf("DeleteRoleError")
-}
-
-func (m *AllErrorMockIam) ListAttachedRolePolicies(ctx context.Context, roleName *string) ([]types.AttachedPolicy, error) {
-	return nil, fmt.Errorf("ListAttachedRolePoliciesError")
-}
-
-func (m *AllErrorMockIam) DetachRolePolicies(ctx context.Context, roleName *string, policies []types.AttachedPolicy) error {
-	return fmt.Errorf("DetachRolePoliciesError")
-}
-
-func (m *AllErrorMockIam) DetachRolePolicy(ctx context.Context, roleName *string, PolicyArn *string) error {
-	return fmt.Errorf("DetachRolePolicyError")
-}
-
-func (m *AllErrorMockIam) CheckRoleExists(ctx context.Context, repositoryName *string) (bool, error) {
-	return false, fmt.Errorf("GetRoleError")
-}
-
-type DeleteRoleErrorMockIam struct{}
-
-func NewDeleteRoleErrorMockIam() *DeleteRoleErrorMockIam {
-	return &DeleteRoleErrorMockIam{}
+// MockIIam is a mock of IIam interface.
+type MockIIam struct {
+	ctrl     *gomock.Controller
+	recorder *MockIIamMockRecorder
 }
 
-func (m *DeleteRoleErrorMockIam) DeleteRole(ctx context.Context, roleName *string) error {
-	return fmt.Errorf("DeleteRoleError")
+// MockIIamMockRecorder is the mock recorder for MockIIam.
+type MockIIamMockRecorder struct {
+	mock *MockIIam
 }
 
-func (m *DeleteRoleErrorMockIam) ListAttachedRolePolicies(ctx context.Context, roleName *string) ([]types.AttachedPolicy, error) {
-	output := []types.AttachedPolicy{
-		{
-			PolicyArn:  aws.String("PolicyArn1"),
-			PolicyName: aws.String("PolicyName1"),
-		},
-		{
-			PolicyArn:  aws.String("PolicyArn2"),
-			PolicyName: aws.String("PolicyName2"),
-		},
-	}
-	return output, nil
+// NewMockIIam creates a new mock instance.
+func NewMockIIam(ctrl *gomock.Controller) *MockIIam {
+	mock := &MockIIam{ctrl: ctrl}
+	mock.recorder = &MockIIamMockRecorder{mock}
+	return mock
 }
 
-func (m *DeleteRoleErrorMockIam) DetachRolePolicies(ctx context.Context, roleName *string, policies []types.AttachedPolicy) error {
-	return nil
+// EXPECT returns an object that allows the caller to indicate expected use.
+func (m *MockIIam) EXPECT() *MockIIamMockRecorder {
+	return m.recorder
 }
 
-func (m *DeleteRoleErrorMockIam) DetachRolePolicy(ctx context.Context, roleName *string, PolicyArn *string) error {
-	return nil
+// CheckRoleExists mocks base method.
+func (m *MockIIam) CheckRoleExists(ctx context.Context, roleName *string) (bool, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "CheckRoleExists", ctx, roleName)
+	ret0, _ := ret[0].(bool)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
 }
 
-func (m *DeleteRoleErrorMockIam) CheckRoleExists(ctx context.Context, repositoryName *string) (bool, error) {
-	return true, nil
+// CheckRoleExists indicates an expected call of CheckRoleExists.
+func (mr *MockIIamMockRecorder) CheckRoleExists(ctx, roleName interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckRoleExists", reflect.TypeOf((*MockIIam)(nil).CheckRoleExists), ctx, roleName)
 }
 
-type ListAttachedRolePoliciesErrorMockIam struct{}
-
-func NewListAttachedRolePoliciesErrorMockIam() *ListAttachedRolePoliciesErrorMockIam {
-	return &ListAttachedRolePoliciesErrorMockIam{}
-}
-
-func (m *ListAttachedRolePoliciesErrorMockIam) DeleteRole(ctx context.Context, roleName *string) error {
-	return nil
-}
-
-func (m *ListAttachedRolePoliciesErrorMockIam) ListAttachedRolePolicies(ctx context.Context, roleName *string) ([]types.AttachedPolicy, error) {
-	return nil, fmt.Errorf("ListAttachedRolePoliciesError")
+// DeleteRole mocks base method.
+func (m *MockIIam) DeleteRole(ctx context.Context, roleName *string) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DeleteRole", ctx, roleName)
+	ret0, _ := ret[0].(error)
+	return ret0
 }
 
-func (m *ListAttachedRolePoliciesErrorMockIam) DetachRolePolicies(ctx context.Context, roleName *string, policies []types.AttachedPolicy) error {
-	return nil
+// DeleteRole indicates an expected call of DeleteRole.
+func (mr *MockIIamMockRecorder) DeleteRole(ctx, roleName interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteRole", reflect.TypeOf((*MockIIam)(nil).DeleteRole), ctx, roleName)
 }
 
-func (m *ListAttachedRolePoliciesErrorMockIam) DetachRolePolicy(ctx context.Context, roleName *string, PolicyArn *string) error {
-	return nil
-}
-
-func (m *ListAttachedRolePoliciesErrorMockIam) CheckRoleExists(ctx context.Context, repositoryName *string) (bool, error) {
-	return true, nil
-}
-
-type DetachRolePoliciesErrorMockIam struct{}
-
-func NewDetachRolePoliciesErrorMockIam() *DetachRolePoliciesErrorMockIam {
-	return &DetachRolePoliciesErrorMockIam{}
-}
-
-func (m *DetachRolePoliciesErrorMockIam) DeleteRole(ctx context.Context, roleName *string) error {
-	return nil
-}
-
-func (m *DetachRolePoliciesErrorMockIam) ListAttachedRolePolicies(ctx context.Context, roleName *string) ([]types.AttachedPolicy, error) {
-	output := []types.AttachedPolicy{
-		{
-			PolicyArn:  aws.String("PolicyArn1"),
-			PolicyName: aws.String("PolicyName1"),
-		},
-		{
-			PolicyArn:  aws.String("PolicyArn2"),
-			PolicyName: aws.String("PolicyName2"),
-		},
-	}
-	return output, nil
-}
-
-func (m *DetachRolePoliciesErrorMockIam) DetachRolePolicies(ctx context.Context, roleName *string, policies []types.AttachedPolicy) error {
-	return fmt.Errorf("DetachRolePoliciesError")
-}
-
-func (m *DetachRolePoliciesErrorMockIam) DetachRolePolicy(ctx context.Context, roleName *string, PolicyArn *string) error {
-	return nil
-}
-
-func (m *DetachRolePoliciesErrorMockIam) CheckRoleExists(ctx context.Context, repositoryName *string) (bool, error) {
-	return true, nil
-}
-
-type DetachRolePoliciesErrorAfterZeroLengthMockIam struct{}
-
-func NewDetachRolePoliciesErrorAfterZeroLengthMockIam() *DetachRolePoliciesErrorAfterZeroLengthMockIam {
-	return &DetachRolePoliciesErrorAfterZeroLengthMockIam{}
-}
-
-func (m *DetachRolePoliciesErrorAfterZeroLengthMockIam) DeleteRole(ctx context.Context, roleName *string) error {
-	return nil
-}
-
-func (m *DetachRolePoliciesErrorAfterZeroLengthMockIam) ListAttachedRolePolicies(ctx context.Context, roleName *string) ([]types.AttachedPolicy, error) {
-	output := []types.AttachedPolicy{}
-	return output, nil
-}
-
-func (m *DetachRolePoliciesErrorAfterZeroLengthMockIam) DetachRolePolicies(ctx context.Context, roleName *string, policies []types.AttachedPolicy) error {
-	return fmt.Errorf("DetachRolePoliciesErrorAfterZeroLength")
-}
-
-func (m *DetachRolePoliciesErrorAfterZeroLengthMockIam) DetachRolePolicy(ctx context.Context, roleName *string, PolicyArn *string) error {
-	return nil
-}
-
-func (m *DetachRolePoliciesErrorAfterZeroLengthMockIam) CheckRoleExists(ctx context.Context, repositoryName *string) (bool, error) {
-	return true, nil
-}
-
-type CheckRoleExistsErrorMockRole struct{}
-
-func NewCheckRoleExistsErrorMockRole() *CheckRoleExistsErrorMockRole {
-	return &CheckRoleExistsErrorMockRole{}
-}
-
-func (m *CheckRoleExistsErrorMockRole) DeleteRole(ctx context.Context, roleName *string) error {
-	return nil
-}
-
-func (m *CheckRoleExistsErrorMockRole) ListAttachedRolePolicies(ctx context.Context, roleName *string) ([]types.AttachedPolicy, error) {
-	output := []types.AttachedPolicy{
-		{
-			PolicyArn:  aws.String("PolicyArn1"),
-			PolicyName: aws.String("PolicyName1"),
-		},
-		{
-			PolicyArn:  aws.String("PolicyArn2"),
-			PolicyName: aws.String("PolicyName2"),
-		},
-	}
-	return output, nil
-}
-
-func (m *CheckRoleExistsErrorMockRole) DetachRolePolicies(ctx context.Context, roleName *string, policies []types.AttachedPolicy) error {
-	return nil
-}
-
-func (m *CheckRoleExistsErrorMockRole) DetachRolePolicy(ctx context.Context, roleName *string, PolicyArn *string) error {
-	return nil
-}
-
-func (m *CheckRoleExistsErrorMockRole) CheckRoleExists(ctx context.Context, repositoryName *string) (bool, error) {
-	return false, fmt.Errorf("GetRoleError")
-}
-
-type CheckRoleNotExistsMockRole struct{}
-
-func NewCheckRoleNotExistsMockRole() *CheckRoleNotExistsMockRole {
-	return &CheckRoleNotExistsMockRole{}
+// DetachRolePolicies mocks base method.
+func (m *MockIIam) DetachRolePolicies(ctx context.Context, roleName *string, policies []types.AttachedPolicy) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DetachRolePolicies", ctx, roleName, policies)
+	ret0, _ := ret[0].(error)
+	return ret0
 }
 
-func (m *CheckRoleNotExistsMockRole) DeleteRole(ctx context.Context, roleName *string) error {
-	return nil
+// DetachRolePolicies indicates an expected call of DetachRolePolicies.
+func (mr *MockIIamMockRecorder) DetachRolePolicies(ctx, roleName, policies interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DetachRolePolicies", reflect.TypeOf((*MockIIam)(nil).DetachRolePolicies), ctx, roleName, policies)
 }
 
-func (m *CheckRoleNotExistsMockRole) ListAttachedRolePolicies(ctx context.Context, roleName *string) ([]types.AttachedPolicy, error) {
-	output := []types.AttachedPolicy{
-		{
-			PolicyArn:  aws.String("PolicyArn1"),
-			PolicyName: aws.String("PolicyName1"),
-		},
-		{
-			PolicyArn:  aws.String("PolicyArn2"),
-			PolicyName: aws.String("PolicyName2"),
-		},
-	}
-	return output, nil
+// DetachRolePolicy mocks base method.
+func (m *MockIIam) DetachRolePolicy(ctx context.Context, roleName, PolicyArn *string) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DetachRolePolicy", ctx, roleName, PolicyArn)
+	ret0, _ := ret[0].(error)
+	return ret0
 }
 
-func (m *CheckRoleNotExistsMockRole) DetachRolePolicies(ctx context.Context, roleName *string, policies []types.AttachedPolicy) error {
-	return nil
+// DetachRolePolicy indicates an expected call of DetachRolePolicy.
+func (mr *MockIIamMockRecorder) DetachRolePolicy(ctx, roleName, PolicyArn interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DetachRolePolicy", reflect.TypeOf((*MockIIam)(nil).DetachRolePolicy), ctx, roleName, PolicyArn)
 }
 
-func (m *CheckRoleNotExistsMockRole) DetachRolePolicy(ctx context.Context, roleName *string, PolicyArn *string) error {
-	return nil
+// ListAttachedRolePolicies mocks base method.
+func (m *MockIIam) ListAttachedRolePolicies(ctx context.Context, roleName *string) ([]types.AttachedPolicy, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "ListAttachedRolePolicies", ctx, roleName)
+	ret0, _ := ret[0].([]types.AttachedPolicy)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
 }
 
-func (m *CheckRoleNotExistsMockRole) CheckRoleExists(ctx context.Context, repositoryName *string) (bool, error) {
-	return false, nil
+// ListAttachedRolePolicies indicates an expected call of ListAttachedRolePolicies.
+func (mr *MockIIamMockRecorder) ListAttachedRolePolicies(ctx, roleName interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListAttachedRolePolicies", reflect.TypeOf((*MockIIam)(nil).ListAttachedRolePolicies), ctx, roleName)
 }
diff --git a/pkg/client/s3.go b/pkg/client/s3.go
index dcc47bd..60d156f 100644
--- a/pkg/client/s3.go
+++ b/pkg/client/s3.go
@@ -1,3 +1,4 @@
+//go:generate mockgen -source=./s3.go -destination=./s3_mock.go -package=client
 package client
 
 import (
diff --git a/pkg/client/s3_mock.go b/pkg/client/s3_mock.go
index e1fa64d..7aeb5c0 100644
--- a/pkg/client/s3_mock.go
+++ b/pkg/client/s3_mock.go
@@ -1,322 +1,95 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: ./s3.go
+
+// Package client is a generated GoMock package.
 package client
 
 import (
-	"context"
-	"fmt"
+	context "context"
+	reflect "reflect"
 
-	"github.com/aws/aws-sdk-go-v2/aws"
-	"github.com/aws/aws-sdk-go-v2/service/s3/types"
+	types "github.com/aws/aws-sdk-go-v2/service/s3/types"
+	gomock "github.com/golang/mock/gomock"
 )
 
-/*
-	Mocks for client
-*/
-
-var _ IS3 = (*MockS3)(nil)
-var _ IS3 = (*AllErrorMockS3)(nil)
-var _ IS3 = (*DeleteObjectsErrorMockS3)(nil)
-var _ IS3 = (*DeleteObjectsErrorAfterZeroLengthMockS3)(nil)
-var _ IS3 = (*DeleteObjectsOutputErrorMockS3)(nil)
-var _ IS3 = (*DeleteObjectsOutputErrorAfterZeroLengthMockS3)(nil)
-var _ IS3 = (*ListObjectVersionsErrorMockS3)(nil)
-var _ IS3 = (*DeleteBucketErrorMockS3)(nil)
-var _ IS3 = (*CheckBucketExistsErrorMockS3)(nil)
-var _ IS3 = (*CheckBucketNotExistsMockS3)(nil)
-
-type MockS3 struct{}
-
-func NewMockS3() *MockS3 {
-	return &MockS3{}
-}
-
-func (m *MockS3) DeleteBucket(ctx context.Context, bucketName *string) error {
-	return nil
+// MockIS3 is a mock of IS3 interface.
+type MockIS3 struct {
+	ctrl     *gomock.Controller
+	recorder *MockIS3MockRecorder
 }
 
-func (m *MockS3) DeleteObjects(ctx context.Context, bucketName *string, objects []types.ObjectIdentifier) ([]types.Error, error) {
-	return []types.Error{}, nil
+// MockIS3MockRecorder is the mock recorder for MockIS3.
+type MockIS3MockRecorder struct {
+	mock *MockIS3
 }
 
-func (m *MockS3) ListObjectVersions(ctx context.Context, bucketName *string) ([]types.ObjectIdentifier, error) {
-	output := []types.ObjectIdentifier{
-		{
-			Key:       aws.String("KeyForVersions"),
-			VersionId: aws.String("VersionIdForVersions"),
-		},
-		{
-			Key:       aws.String("KeyForDeleteMarkers"),
-			VersionId: aws.String("VersionIdForDeleteMarkers"),
-		},
-	}
-	return output, nil
+// NewMockIS3 creates a new mock instance.
+func NewMockIS3(ctrl *gomock.Controller) *MockIS3 {
+	mock := &MockIS3{ctrl: ctrl}
+	mock.recorder = &MockIS3MockRecorder{mock}
+	return mock
 }
 
-func (m *MockS3) CheckBucketExists(ctx context.Context, bucketName *string) (bool, error) {
-	return true, nil
+// EXPECT returns an object that allows the caller to indicate expected use.
+func (m *MockIS3) EXPECT() *MockIS3MockRecorder {
+	return m.recorder
 }
 
-type AllErrorMockS3 struct{}
-
-func NewAllErrorMockS3() *AllErrorMockS3 {
-	return &AllErrorMockS3{}
-}
-
-func (m *AllErrorMockS3) DeleteBucket(ctx context.Context, bucketName *string) error {
-	return fmt.Errorf("DeleteBucketError")
+// CheckBucketExists mocks base method.
+func (m *MockIS3) CheckBucketExists(ctx context.Context, bucketName *string) (bool, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "CheckBucketExists", ctx, bucketName)
+	ret0, _ := ret[0].(bool)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
 }
 
-func (m *AllErrorMockS3) DeleteObjects(ctx context.Context, bucketName *string, objects []types.ObjectIdentifier) ([]types.Error, error) {
-	return []types.Error{}, fmt.Errorf("DeleteObjectsError")
+// CheckBucketExists indicates an expected call of CheckBucketExists.
+func (mr *MockIS3MockRecorder) CheckBucketExists(ctx, bucketName interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckBucketExists", reflect.TypeOf((*MockIS3)(nil).CheckBucketExists), ctx, bucketName)
 }
 
-func (m *AllErrorMockS3) ListObjectVersions(ctx context.Context, bucketName *string) ([]types.ObjectIdentifier, error) {
-	return nil, fmt.Errorf("ListObjectVersionsError")
+// DeleteBucket mocks base method.
+func (m *MockIS3) DeleteBucket(ctx context.Context, bucketName *string) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DeleteBucket", ctx, bucketName)
+	ret0, _ := ret[0].(error)
+	return ret0
 }
 
-func (m *AllErrorMockS3) CheckBucketExists(ctx context.Context, bucketName *string) (bool, error) {
-	return false, fmt.Errorf("ListBucketsError")
-}
-
-type DeleteBucketErrorMockS3 struct{}
-
-func NewDeleteBucketErrorMockS3() *DeleteBucketErrorMockS3 {
-	return &DeleteBucketErrorMockS3{}
-}
-
-func (m *DeleteBucketErrorMockS3) DeleteBucket(ctx context.Context, bucketName *string) error {
-	return fmt.Errorf("DeleteBucketError")
-}
-
-func (m *DeleteBucketErrorMockS3) DeleteObjects(ctx context.Context, bucketName *string, objects []types.ObjectIdentifier) ([]types.Error, error) {
-	return []types.Error{}, nil
-}
-
-func (m *DeleteBucketErrorMockS3) ListObjectVersions(ctx context.Context, bucketName *string) ([]types.ObjectIdentifier, error) {
-	output := []types.ObjectIdentifier{
-		{
-			Key:       aws.String("KeyForVersions"),
-			VersionId: aws.String("VersionIdForVersions"),
-		},
-		{
-			Key:       aws.String("KeyForDeleteMarkers"),
-			VersionId: aws.String("VersionIdForDeleteMarkers"),
-		},
-	}
-	return output, nil
-}
-
-func (m *DeleteBucketErrorMockS3) CheckBucketExists(ctx context.Context, bucketName *string) (bool, error) {
-	return true, nil
-}
-
-type DeleteObjectsErrorMockS3 struct{}
-
-func NewDeleteObjectsErrorMockS3() *DeleteObjectsErrorMockS3 {
-	return &DeleteObjectsErrorMockS3{}
-}
-
-func (m *DeleteObjectsErrorMockS3) DeleteBucket(ctx context.Context, bucketName *string) error {
-	return nil
-}
-
-func (m *DeleteObjectsErrorMockS3) DeleteObjects(ctx context.Context, bucketName *string, objects []types.ObjectIdentifier) ([]types.Error, error) {
-	return []types.Error{}, fmt.Errorf("DeleteObjectsError")
-}
-
-func (m *DeleteObjectsErrorMockS3) ListObjectVersions(ctx context.Context, bucketName *string) ([]types.ObjectIdentifier, error) {
-	output := []types.ObjectIdentifier{
-		{
-			Key:       aws.String("KeyForVersions"),
-			VersionId: aws.String("VersionIdForVersions"),
-		},
-		{
-			Key:       aws.String("KeyForDeleteMarkers"),
-			VersionId: aws.String("VersionIdForDeleteMarkers"),
-		},
-	}
-	return output, nil
-}
-
-func (m *DeleteObjectsErrorMockS3) CheckBucketExists(ctx context.Context, bucketName *string) (bool, error) {
-	return true, nil
-}
-
-type DeleteObjectsErrorAfterZeroLengthMockS3 struct{}
-
-func NewDeleteObjectsErrorAfterZeroLengthMockS3() *DeleteObjectsErrorAfterZeroLengthMockS3 {
-	return &DeleteObjectsErrorAfterZeroLengthMockS3{}
-}
-
-func (m *DeleteObjectsErrorAfterZeroLengthMockS3) DeleteBucket(ctx context.Context, bucketName *string) error {
-	return nil
-}
-
-func (m *DeleteObjectsErrorAfterZeroLengthMockS3) DeleteObjects(ctx context.Context, bucketName *string, objects []types.ObjectIdentifier) ([]types.Error, error) {
-	return []types.Error{}, fmt.Errorf("DeleteObjectsErrorAfterZeroLength")
-}
-
-func (m *DeleteObjectsErrorAfterZeroLengthMockS3) ListObjectVersions(ctx context.Context, bucketName *string) ([]types.ObjectIdentifier, error) {
-	output := []types.ObjectIdentifier{}
-	return output, nil
-}
-
-func (m *DeleteObjectsErrorAfterZeroLengthMockS3) CheckBucketExists(ctx context.Context, bucketName *string) (bool, error) {
-	return true, nil
-}
-
-type DeleteObjectsOutputErrorMockS3 struct{}
-
-func NewDeleteObjectsOutputErrorMockS3() *DeleteObjectsOutputErrorMockS3 {
-	return &DeleteObjectsOutputErrorMockS3{}
-}
-
-func (m *DeleteObjectsOutputErrorMockS3) DeleteBucket(ctx context.Context, bucketName *string) error {
-	return nil
-}
-
-func (m *DeleteObjectsOutputErrorMockS3) DeleteObjects(ctx context.Context, bucketName *string, objects []types.ObjectIdentifier) ([]types.Error, error) {
-	output := []types.Error{
-		{
-			Key:       aws.String("Key"),
-			Code:      aws.String("Code"),
-			Message:   aws.String("Message"),
-			VersionId: aws.String("VersionId"),
-		},
-	}
-	return output, nil
-}
-
-func (m *DeleteObjectsOutputErrorMockS3) ListObjectVersions(ctx context.Context, bucketName *string) ([]types.ObjectIdentifier, error) {
-	output := []types.ObjectIdentifier{
-		{
-			Key:       aws.String("KeyForVersions"),
-			VersionId: aws.String("VersionIdForVersions"),
-		},
-		{
-			Key:       aws.String("KeyForDeleteMarkers"),
-			VersionId: aws.String("VersionIdForDeleteMarkers"),
-		},
-	}
-	return output, nil
-}
-
-func (m *DeleteObjectsOutputErrorMockS3) CheckBucketExists(ctx context.Context, bucketName *string) (bool, error) {
-	return true, nil
-}
-
-type DeleteObjectsOutputErrorAfterZeroLengthMockS3 struct{}
-
-func NewDeleteObjectsOutputErrorAfterZeroLengthMockS3() *DeleteObjectsOutputErrorAfterZeroLengthMockS3 {
-	return &DeleteObjectsOutputErrorAfterZeroLengthMockS3{}
-}
-
-func (m *DeleteObjectsOutputErrorAfterZeroLengthMockS3) DeleteBucket(ctx context.Context, bucketName *string) error {
-	return nil
-}
-
-func (m *DeleteObjectsOutputErrorAfterZeroLengthMockS3) DeleteObjects(ctx context.Context, bucketName *string, objects []types.ObjectIdentifier) ([]types.Error, error) {
-	output := []types.Error{
-		{
-			Key:       aws.String("Key"),
-			Code:      aws.String("Code"),
-			Message:   aws.String("Message"),
-			VersionId: aws.String("VersionId"),
-		},
-	}
-	return output, nil
-}
-
-func (m *DeleteObjectsOutputErrorAfterZeroLengthMockS3) ListObjectVersions(ctx context.Context, bucketName *string) ([]types.ObjectIdentifier, error) {
-	output := []types.ObjectIdentifier{}
-	return output, nil
-}
-
-func (m *DeleteObjectsOutputErrorAfterZeroLengthMockS3) CheckBucketExists(ctx context.Context, bucketName *string) (bool, error) {
-	return true, nil
-}
-
-type ListObjectVersionsErrorMockS3 struct{}
-
-func NewListObjectVersionsErrorMockS3() *ListObjectVersionsErrorMockS3 {
-	return &ListObjectVersionsErrorMockS3{}
-}
-
-func (m *ListObjectVersionsErrorMockS3) DeleteBucket(ctx context.Context, bucketName *string) error {
-	return nil
-}
-
-func (m *ListObjectVersionsErrorMockS3) DeleteObjects(ctx context.Context, bucketName *string, objects []types.ObjectIdentifier) ([]types.Error, error) {
-	return []types.Error{}, nil
-}
-
-func (m *ListObjectVersionsErrorMockS3) ListObjectVersions(ctx context.Context, bucketName *string) ([]types.ObjectIdentifier, error) {
-	return nil, fmt.Errorf("ListObjectVersionsError")
-}
-
-func (m *ListObjectVersionsErrorMockS3) CheckBucketExists(ctx context.Context, bucketName *string) (bool, error) {
-	return true, nil
-}
-
-type CheckBucketExistsErrorMockS3 struct{}
-
-func NewCheckBucketExistsErrorMockS3() *CheckBucketExistsErrorMockS3 {
-	return &CheckBucketExistsErrorMockS3{}
-}
-
-func (m *CheckBucketExistsErrorMockS3) DeleteBucket(ctx context.Context, bucketName *string) error {
-	return nil
-}
-
-func (m *CheckBucketExistsErrorMockS3) DeleteObjects(ctx context.Context, bucketName *string, objects []types.ObjectIdentifier) ([]types.Error, error) {
-	return []types.Error{}, nil
-}
-
-func (m *CheckBucketExistsErrorMockS3) ListObjectVersions(ctx context.Context, bucketName *string) ([]types.ObjectIdentifier, error) {
-	output := []types.ObjectIdentifier{
-		{
-			Key:       aws.String("KeyForVersions"),
-			VersionId: aws.String("VersionIdForVersions"),
-		},
-		{
-			Key:       aws.String("KeyForDeleteMarkers"),
-			VersionId: aws.String("VersionIdForDeleteMarkers"),
-		},
-	}
-	return output, nil
-}
-
-func (m *CheckBucketExistsErrorMockS3) CheckBucketExists(ctx context.Context, bucketName *string) (bool, error) {
-	return false, fmt.Errorf("ListBucketsError")
-}
-
-type CheckBucketNotExistsMockS3 struct{}
-
-func NewCheckBucketNotExistsMockS3() *CheckBucketNotExistsMockS3 {
-	return &CheckBucketNotExistsMockS3{}
+// DeleteBucket indicates an expected call of DeleteBucket.
+func (mr *MockIS3MockRecorder) DeleteBucket(ctx, bucketName interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteBucket", reflect.TypeOf((*MockIS3)(nil).DeleteBucket), ctx, bucketName)
 }
 
-func (m *CheckBucketNotExistsMockS3) DeleteBucket(ctx context.Context, bucketName *string) error {
-	return nil
+// DeleteObjects mocks base method.
+func (m *MockIS3) DeleteObjects(ctx context.Context, bucketName *string, objects []types.ObjectIdentifier) ([]types.Error, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DeleteObjects", ctx, bucketName, objects)
+	ret0, _ := ret[0].([]types.Error)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
 }
 
-func (m *CheckBucketNotExistsMockS3) DeleteObjects(ctx context.Context, bucketName *string, objects []types.ObjectIdentifier) ([]types.Error, error) {
-	return []types.Error{}, nil
+// DeleteObjects indicates an expected call of DeleteObjects.
+func (mr *MockIS3MockRecorder) DeleteObjects(ctx, bucketName, objects interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteObjects", reflect.TypeOf((*MockIS3)(nil).DeleteObjects), ctx, bucketName, objects)
 }
 
-func (m *CheckBucketNotExistsMockS3) ListObjectVersions(ctx context.Context, bucketName *string) ([]types.ObjectIdentifier, error) {
-	output := []types.ObjectIdentifier{
-		{
-			Key:       aws.String("KeyForVersions"),
-			VersionId: aws.String("VersionIdForVersions"),
-		},
-		{
-			Key:       aws.String("KeyForDeleteMarkers"),
-			VersionId: aws.String("VersionIdForDeleteMarkers"),
-		},
-	}
-	return output, nil
+// ListObjectVersions mocks base method.
+func (m *MockIS3) ListObjectVersions(ctx context.Context, bucketName *string) ([]types.ObjectIdentifier, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "ListObjectVersions", ctx, bucketName)
+	ret0, _ := ret[0].([]types.ObjectIdentifier)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
 }
 
-func (m *CheckBucketNotExistsMockS3) CheckBucketExists(ctx context.Context, bucketName *string) (bool, error) {
-	return false, nil
+// ListObjectVersions indicates an expected call of ListObjectVersions.
+func (mr *MockIS3MockRecorder) ListObjectVersions(ctx, bucketName interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListObjectVersions", reflect.TypeOf((*MockIS3)(nil).ListObjectVersions), ctx, bucketName)
 }


Test patch:
diff --git a/internal/operation/backup_vault_test.go b/internal/operation/backup_vault_test.go
index df33a02..273dd6a 100644
--- a/internal/operation/backup_vault_test.go
+++ b/internal/operation/backup_vault_test.go
@@ -6,9 +6,11 @@ import (
 	"testing"
 
 	"github.com/aws/aws-sdk-go-v2/aws"
+	"github.com/aws/aws-sdk-go-v2/service/backup/types"
 	cfnTypes "github.com/aws/aws-sdk-go-v2/service/cloudformation/types"
 	"github.com/go-to-k/delstack/internal/io"
 	"github.com/go-to-k/delstack/pkg/client"
+	gomock "github.com/golang/mock/gomock"
 )
 
 /*
@@ -17,63 +19,64 @@ import (
 
 func TestBackupVaultOperator_DeleteBackupVault(t *testing.T) {
 	io.NewLogger(false)
-	mock := client.NewMockBackup()
-	allErrorMock := client.NewAllErrorMockBackup()
-	listRecoveryPointsErrorMock := client.NewListRecoveryPointsErrorMockBackup()
-	deleteRecoveryPointsErrorMock := client.NewDeleteRecoveryPointsErrorMockBackup()
-	deleteRecoveryPointsErrorAfterZeroLengthMock := client.NewDeleteRecoveryPointsErrorAfterZeroLengthMockBackup()
-	deleteBackupVaultErrorMock := client.NewDeleteBackupVaultErrorMockBackup()
-	checkBackupVaultExistsErrorMock := client.NewCheckBackupVaultExistsErrorMockBackup()
-	checkBackupVaultNotExistsMock := client.NewCheckBackupVaultNotExistsMockBackup()
 
 	type args struct {
 		ctx             context.Context
 		backupVaultName *string
-		client          client.IBackup
 	}
 
 	cases := []struct {
-		name    string
-		args    args
-		want    error
-		wantErr bool
+		name          string
+		args          args
+		prepareMockFn func(m *client.MockIBackup)
+		want          error
+		wantErr       bool
 	}{
 		{
 			name: "delete backup vault successfully",
 			args: args{
 				ctx:             context.Background(),
 				backupVaultName: aws.String("test"),
-				client:          mock,
+			},
+			prepareMockFn: func(m *client.MockIBackup) {
+				m.EXPECT().CheckBackupVaultExists(gomock.Any(), aws.String("test")).Return(true, nil)
+				m.EXPECT().ListRecoveryPointsByBackupVault(gomock.Any(), aws.String("test")).Return(
+					[]types.RecoveryPointByBackupVault{
+						{
+							BackupVaultName: aws.String("BackupVaultName1"),
+							BackupVaultArn:  aws.String("BackupVaultArn1"),
+						},
+						{
+							BackupVaultName: aws.String("BackupVaultName2"),
+							BackupVaultArn:  aws.String("BackupVaultArn2"),
+						},
+					}, nil)
+				m.EXPECT().DeleteRecoveryPoints(gomock.Any(), aws.String("test"), gomock.Any()).Return(nil)
+				m.EXPECT().DeleteBackupVault(gomock.Any(), aws.String("test")).Return(nil)
 			},
 			want:    nil,
 			wantErr: false,
 		},
 		{
-			name: "delete backup vault failure for all errors",
+			name: "delete backup vault failure for check backup vault exists errors",
 			args: args{
 				ctx:             context.Background(),
 				backupVaultName: aws.String("test"),
-				client:          allErrorMock,
 			},
-			want:    fmt.Errorf("ListBackupVaultsError"),
-			wantErr: true,
-		},
-		{
-			name: "delete bucket failure for check bucket exists errors",
-			args: args{
-				ctx:             context.Background(),
-				backupVaultName: aws.String("test"),
-				client:          checkBackupVaultExistsErrorMock,
+			prepareMockFn: func(m *client.MockIBackup) {
+				m.EXPECT().CheckBackupVaultExists(gomock.Any(), aws.String("test")).Return(false, fmt.Errorf("ListBackupVaultsError"))
 			},
 			want:    fmt.Errorf("ListBackupVaultsError"),
 			wantErr: true,
 		},
 		{
-			name: "delete bucket successfully for bucket not exists",
+			name: "delete backup vault successfully for backup vault not exists",
 			args: args{
 				ctx:             context.Background(),
 				backupVaultName: aws.String("test"),
-				client:          checkBackupVaultNotExistsMock,
+			},
+			prepareMockFn: func(m *client.MockIBackup) {
+				m.EXPECT().CheckBackupVaultExists(gomock.Any(), aws.String("test")).Return(false, nil)
 			},
 			want:    nil,
 			wantErr: false,
@@ -83,7 +86,10 @@ func TestBackupVaultOperator_DeleteBackupVault(t *testing.T) {
 			args: args{
 				ctx:             context.Background(),
 				backupVaultName: aws.String("test"),
-				client:          listRecoveryPointsErrorMock,
+			},
+			prepareMockFn: func(m *client.MockIBackup) {
+				m.EXPECT().CheckBackupVaultExists(gomock.Any(), aws.String("test")).Return(true, nil)
+				m.EXPECT().ListRecoveryPointsByBackupVault(gomock.Any(), aws.String("test")).Return(nil, fmt.Errorf("ListRecoveryPointsByBackupVaultError"))
 			},
 			want:    fmt.Errorf("ListRecoveryPointsByBackupVaultError"),
 			wantErr: true,
@@ -93,7 +99,21 @@ func TestBackupVaultOperator_DeleteBackupVault(t *testing.T) {
 			args: args{
 				ctx:             context.Background(),
 				backupVaultName: aws.String("test"),
-				client:          deleteRecoveryPointsErrorMock,
+			},
+			prepareMockFn: func(m *client.MockIBackup) {
+				m.EXPECT().CheckBackupVaultExists(gomock.Any(), aws.String("test")).Return(true, nil)
+				m.EXPECT().ListRecoveryPointsByBackupVault(gomock.Any(), aws.String("test")).Return(
+					[]types.RecoveryPointByBackupVault{
+						{
+							BackupVaultName: aws.String("BackupVaultName1"),
+							BackupVaultArn:  aws.String("BackupVaultArn1"),
+						},
+						{
+							BackupVaultName: aws.String("BackupVaultName2"),
+							BackupVaultArn:  aws.String("BackupVaultArn2"),
+						},
+					}, nil)
+				m.EXPECT().DeleteRecoveryPoints(gomock.Any(), aws.String("test"), gomock.Any()).Return(fmt.Errorf("DeleteRecoveryPointsError"))
 			},
 			want:    fmt.Errorf("DeleteRecoveryPointsError"),
 			wantErr: true,
@@ -103,7 +123,11 @@ func TestBackupVaultOperator_DeleteBackupVault(t *testing.T) {
 			args: args{
 				ctx:             context.Background(),
 				backupVaultName: aws.String("test"),
-				client:          deleteRecoveryPointsErrorAfterZeroLengthMock,
+			},
+			prepareMockFn: func(m *client.MockIBackup) {
+				m.EXPECT().CheckBackupVaultExists(gomock.Any(), aws.String("test")).Return(true, nil)
+				m.EXPECT().ListRecoveryPointsByBackupVault(gomock.Any(), aws.String("test")).Return([]types.RecoveryPointByBackupVault{}, nil)
+				m.EXPECT().DeleteBackupVault(gomock.Any(), aws.String("test")).Return(nil)
 			},
 			want:    nil,
 			wantErr: false,
@@ -113,7 +137,22 @@ func TestBackupVaultOperator_DeleteBackupVault(t *testing.T) {
 			args: args{
 				ctx:             context.Background(),
 				backupVaultName: aws.String("test"),
-				client:          deleteBackupVaultErrorMock,
+			},
+			prepareMockFn: func(m *client.MockIBackup) {
+				m.EXPECT().CheckBackupVaultExists(gomock.Any(), aws.String("test")).Return(true, nil)
+				m.EXPECT().ListRecoveryPointsByBackupVault(gomock.Any(), aws.String("test")).Return(
+					[]types.RecoveryPointByBackupVault{
+						{
+							BackupVaultName: aws.String("BackupVaultName1"),
+							BackupVaultArn:  aws.String("BackupVaultArn1"),
+						},
+						{
+							BackupVaultName: aws.String("BackupVaultName2"),
+							BackupVaultArn:  aws.String("BackupVaultArn2"),
+						},
+					}, nil)
+				m.EXPECT().DeleteRecoveryPoints(gomock.Any(), aws.String("test"), gomock.Any()).Return(nil)
+				m.EXPECT().DeleteBackupVault(gomock.Any(), aws.String("test")).Return(fmt.Errorf("DeleteBackupVaultError"))
 			},
 			want:    fmt.Errorf("DeleteBackupVaultError"),
 			wantErr: true,
@@ -122,7 +161,11 @@ func TestBackupVaultOperator_DeleteBackupVault(t *testing.T) {
 
 	for _, tt := range cases {
 		t.Run(tt.name, func(t *testing.T) {
-			backupOperator := NewBackupVaultOperator(tt.args.client)
+			ctrl := gomock.NewController(t)
+			backupMock := client.NewMockIBackup(ctrl)
+			tt.prepareMockFn(backupMock)
+
+			backupOperator := NewBackupVaultOperator(backupMock)
 
 			err := backupOperator.DeleteBackupVault(tt.args.ctx, tt.args.backupVaultName)
 			if (err != nil) != tt.wantErr {
@@ -139,25 +182,38 @@ func TestBackupVaultOperator_DeleteBackupVault(t *testing.T) {
 
 func TestBackupVaultOperator_DeleteResourcesForBackupVault(t *testing.T) {
 	io.NewLogger(false)
-	mock := client.NewMockBackup()
-	allErrorMock := client.NewAllErrorMockBackup()
 
 	type args struct {
-		ctx    context.Context
-		client client.IBackup
+		ctx context.Context
 	}
 
 	cases := []struct {
-		name    string
-		args    args
-		want    error
-		wantErr bool
+		name          string
+		args          args
+		prepareMockFn func(m *client.MockIBackup)
+		want          error
+		wantErr       bool
 	}{
 		{
 			name: "delete resources successfully",
 			args: args{
-				ctx:    context.Background(),
-				client: mock,
+				ctx: context.Background(),
+			},
+			prepareMockFn: func(m *client.MockIBackup) {
+				m.EXPECT().CheckBackupVaultExists(gomock.Any(), aws.String("PhysicalResourceId1")).Return(true, nil)
+				m.EXPECT().ListRecoveryPointsByBackupVault(gomock.Any(), aws.String("PhysicalResourceId1")).Return(
+					[]types.RecoveryPointByBackupVault{
+						{
+							BackupVaultName: aws.String("BackupVaultName1"),
+							BackupVaultArn:  aws.String("BackupVaultArn1"),
+						},
+						{
+							BackupVaultName: aws.String("BackupVaultName2"),
+							BackupVaultArn:  aws.String("BackupVaultArn2"),
+						},
+					}, nil)
+				m.EXPECT().DeleteRecoveryPoints(gomock.Any(), aws.String("PhysicalResourceId1"), gomock.Any()).Return(nil)
+				m.EXPECT().DeleteBackupVault(gomock.Any(), aws.String("PhysicalResourceId1")).Return(nil)
 			},
 			want:    nil,
 			wantErr: false,
@@ -165,8 +221,10 @@ func TestBackupVaultOperator_DeleteResourcesForBackupVault(t *testing.T) {
 		{
 			name: "delete resources failure",
 			args: args{
-				ctx:    context.Background(),
-				client: allErrorMock,
+				ctx: context.Background(),
+			},
+			prepareMockFn: func(m *client.MockIBackup) {
+				m.EXPECT().CheckBackupVaultExists(gomock.Any(), aws.String("PhysicalResourceId1")).Return(false, fmt.Errorf("ListBackupVaultsError"))
 			},
 			want:    fmt.Errorf("ListBackupVaultsError"),
 			wantErr: true,
@@ -175,7 +233,12 @@ func TestBackupVaultOperator_DeleteResourcesForBackupVault(t *testing.T) {
 
 	for _, tt := range cases {
 		t.Run(tt.name, func(t *testing.T) {
-			backupOperator := NewBackupVaultOperator(tt.args.client)
+			ctrl := gomock.NewController(t)
+			backupMock := client.NewMockIBackup(ctrl)
+			tt.prepareMockFn(backupMock)
+
+			backupOperator := NewBackupVaultOperator(backupMock)
+
 			backupOperator.AddResource(&cfnTypes.StackResourceSummary{
 				LogicalResourceId:  aws.String("LogicalResourceId1"),
 				ResourceStatus:     "DELETE_FAILED",
diff --git a/internal/operation/cloudformation_stack_test.go b/internal/operation/cloudformation_stack_test.go
index e9838c2..8bf61c1 100644
--- a/internal/operation/cloudformation_stack_test.go
+++ b/internal/operation/cloudformation_stack_test.go
@@ -7,8 +7,11 @@ import (
 	"testing"
 
 	"github.com/aws/aws-sdk-go-v2/aws"
+	"github.com/aws/aws-sdk-go-v2/service/cloudformation"
+	"github.com/aws/aws-sdk-go-v2/service/cloudformation/types"
 	"github.com/go-to-k/delstack/internal/io"
 	"github.com/go-to-k/delstack/pkg/client"
+	gomock "github.com/golang/mock/gomock"
 )
 
 /*
@@ -18,254 +21,979 @@ import (
 func TestCloudFormationStackOperator_DeleteCloudFormationStack(t *testing.T) {
 	io.NewLogger(false)
 
-	mock := client.NewMockCloudFormation()
-	terminationProtectionIsEnabledMock := client.NewTerminationProtectionIsEnabledMockCloudFormation()
-	notDeleteFailedMock := client.NewNotDeleteFailedMockCloudFormation()
-	allErrorMock := client.NewAllErrorMockCloudFormation()
-	deleteStackErrorMock := client.NewDeleteStackErrorMockCloudFormation()
-	describeStacksErrorMock := client.NewDescribeStacksErrorMockCloudFormation()
-	describeStacksNotExistsErrorMock := client.NewDescribeStacksNotExistsErrorMockCloudFormation()
-	listStackResourcesErrorMock := client.NewListStackResourcesErrorMockCloudFormation()
-
-	mockOperatorManager := NewMockOperatorManager()
-	allErrorMockOperatorManager := NewAllErrorMockOperatorManager()
-	checkResourceCountsErrorMockOperatorManager := NewCheckResourceCountsErrorMockOperatorManager()
-	deleteResourceCollectionErrorMockOperatorManager := NewDeleteResourceCollectionErrorMockOperatorManager()
-
 	type args struct {
-		ctx                 context.Context
-		stackName           *string
-		isRootStack         bool
-		clientMock          client.ICloudFormation
-		operatorManagerMock IOperatorManager
+		ctx         context.Context
+		stackName   *string
+		isRootStack bool
 	}
 
 	cases := []struct {
-		name    string
-		args    args
-		want    error
-		wantErr bool
+		name                         string
+		args                         args
+		prepareMockCloudFormationFn  func(m *client.MockICloudFormation)
+		prepareMockOperatorManagerFn func(m *MockIOperatorManager)
+		want                         error
+		wantErr                      bool
 	}{
 		{
 			name: "delete stack successfully for root stack",
 			args: args{
-				ctx:                 context.Background(),
-				stackName:           aws.String("test"),
-				isRootStack:         true,
-				clientMock:          mock,
-				operatorManagerMock: mockOperatorManager,
+				ctx:         context.Background(),
+				stackName:   aws.String("test"),
+				isRootStack: true,
 			},
-			want:    nil,
-			wantErr: false,
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "DELETE_FAILED",
+								EnableTerminationProtection: aws.Bool(false),
+							},
+						},
+					},
+					true,
+					nil,
+				)
+
+				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
+
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "DELETE_FAILED",
+								EnableTerminationProtection: aws.Bool(false),
+							},
+						},
+					},
+					false,
+					nil,
+				)
+			},
+			prepareMockOperatorManagerFn: func(m *MockIOperatorManager) {},
+			want:                         nil,
+			wantErr:                      false,
 		},
 		{
 			name: "delete stack successfully for child stack",
 			args: args{
-				ctx:                 context.Background(),
-				stackName:           aws.String("test"),
-				isRootStack:         false,
-				clientMock:          mock,
-				operatorManagerMock: mockOperatorManager,
+				ctx:         context.Background(),
+				stackName:   aws.String("test"),
+				isRootStack: false,
 			},
-			want:    nil,
-			wantErr: false,
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "DELETE_FAILED",
+								EnableTerminationProtection: aws.Bool(false),
+							},
+						},
+					},
+					true,
+					nil,
+				)
+
+				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
+
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "DELETE_FAILED",
+								EnableTerminationProtection: aws.Bool(false),
+							},
+						},
+					},
+					false,
+					nil,
+				)
+			},
+			prepareMockOperatorManagerFn: func(m *MockIOperatorManager) {},
+			want:                         nil,
+			wantErr:                      false,
 		},
 		{
-			name: "delete stack failure for TerminationProtection is enabled stack",
+			name: "delete stack failure for root stack for TerminationProtection is enabled stack",
 			args: args{
-				ctx:                 context.Background(),
-				stackName:           aws.String("test"),
-				isRootStack:         true,
-				clientMock:          terminationProtectionIsEnabledMock,
-				operatorManagerMock: mockOperatorManager,
+				ctx:         context.Background(),
+				stackName:   aws.String("test"),
+				isRootStack: true,
 			},
-			want:    fmt.Errorf("TerminationProtectionIsEnabled: test"),
-			wantErr: true,
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "CREATE_COMPLETE",
+								EnableTerminationProtection: aws.Bool(true),
+							},
+						},
+					},
+					true,
+					nil,
+				)
+			},
+			prepareMockOperatorManagerFn: func(m *MockIOperatorManager) {},
+			want:                         fmt.Errorf("TerminationProtectionIsEnabled: test"),
+			wantErr:                      true,
 		},
 		{
-			name: "delete stack failure for not DELETE_FAILED stack",
+			name: "delete stack failure for child stack for TerminationProtection is enabled stack",
 			args: args{
-				ctx:                 context.Background(),
-				stackName:           aws.String("test"),
-				isRootStack:         true,
-				clientMock:          notDeleteFailedMock,
-				operatorManagerMock: mockOperatorManager,
+				ctx:         context.Background(),
+				stackName:   aws.String("test"),
+				isRootStack: false,
 			},
-			want:    fmt.Errorf("StackStatusError: StackStatus is expected to be DELETE_FAILED, but UPDATE_ROLLBACK_COMPLETE: test"),
-			wantErr: true,
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "CREATE_COMPLETE",
+								EnableTerminationProtection: aws.Bool(true),
+							},
+						},
+					},
+					true,
+					nil,
+				)
+			},
+			prepareMockOperatorManagerFn: func(m *MockIOperatorManager) {},
+			want:                         fmt.Errorf("TerminationProtectionIsEnabled: test"),
+			wantErr:                      true,
 		},
 		{
-			name: "delete stack failure for root stack for all errors",
+			name: "delete stack failure for root stack for not DELETE_FAILED stack",
 			args: args{
-				ctx:                 context.Background(),
-				stackName:           aws.String("test"),
-				isRootStack:         true,
-				clientMock:          allErrorMock,
-				operatorManagerMock: mockOperatorManager,
+				ctx:         context.Background(),
+				stackName:   aws.String("test"),
+				isRootStack: true,
 			},
-			want:    fmt.Errorf("DescribeStacksError"),
-			wantErr: true,
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "UPDATE_ROLLBACK_COMPLETE",
+								EnableTerminationProtection: aws.Bool(false),
+							},
+						},
+					},
+					true,
+					nil,
+				).AnyTimes()
+
+				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
+			},
+			prepareMockOperatorManagerFn: func(m *MockIOperatorManager) {},
+			want:                         fmt.Errorf("StackStatusError: StackStatus is expected to be DELETE_FAILED, but UPDATE_ROLLBACK_COMPLETE: test"),
+			wantErr:                      true,
 		},
 		{
-			name: "delete stack failure for child stack for all errors",
+			name: "delete stack failure for child stack for not DELETE_FAILED stack",
 			args: args{
-				ctx:                 context.Background(),
-				stackName:           aws.String("test"),
-				isRootStack:         false,
-				clientMock:          allErrorMock,
-				operatorManagerMock: mockOperatorManager,
+				ctx:         context.Background(),
+				stackName:   aws.String("test"),
+				isRootStack: false,
 			},
-			want:    fmt.Errorf("DescribeStacksError"),
-			wantErr: true,
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "UPDATE_ROLLBACK_COMPLETE",
+								EnableTerminationProtection: aws.Bool(false),
+							},
+						},
+					},
+					true,
+					nil,
+				).AnyTimes()
+
+				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
+			},
+			prepareMockOperatorManagerFn: func(m *MockIOperatorManager) {},
+			want:                         fmt.Errorf("StackStatusError: StackStatus is expected to be DELETE_FAILED, but UPDATE_ROLLBACK_COMPLETE: test"),
+			wantErr:                      true,
 		},
 		{
-			name: "delete stack failure for root stack for delete Stack",
+			name: "delete stack failure for root stack for delete stack error",
 			args: args{
-				ctx:                 context.Background(),
-				stackName:           aws.String("test"),
-				isRootStack:         true,
-				clientMock:          deleteStackErrorMock,
-				operatorManagerMock: mockOperatorManager,
+				ctx:         context.Background(),
+				stackName:   aws.String("test"),
+				isRootStack: true,
 			},
-			want:    fmt.Errorf("DeleteStackError"),
-			wantErr: true,
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "DELETE_FAILED",
+								EnableTerminationProtection: aws.Bool(false),
+							},
+						},
+					},
+					true,
+					nil,
+				)
+
+				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(fmt.Errorf("DeleteStackError"))
+			},
+			prepareMockOperatorManagerFn: func(m *MockIOperatorManager) {},
+			want:                         fmt.Errorf("DeleteStackError"),
+			wantErr:                      true,
 		},
 		{
-			name: "delete stack failure for child stack for delete Stack",
+			name: "delete stack failure for child stack for delete stack error",
 			args: args{
-				ctx:                 context.Background(),
-				stackName:           aws.String("test"),
-				isRootStack:         false,
-				clientMock:          deleteStackErrorMock,
-				operatorManagerMock: mockOperatorManager,
+				ctx:         context.Background(),
+				stackName:   aws.String("test"),
+				isRootStack: false,
 			},
-			want:    fmt.Errorf("DeleteStackError"),
-			wantErr: true,
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "DELETE_FAILED",
+								EnableTerminationProtection: aws.Bool(false),
+							},
+						},
+					},
+					true,
+					nil,
+				)
+
+				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(fmt.Errorf("DeleteStackError"))
+			},
+			prepareMockOperatorManagerFn: func(m *MockIOperatorManager) {},
+			want:                         fmt.Errorf("DeleteStackError"),
+			wantErr:                      true,
 		},
 		{
-			name: "delete stack failure for root stack for describe stacks",
+			name: "delete stack failure for root stack for describe stacks error",
 			args: args{
-				ctx:                 context.Background(),
-				stackName:           aws.String("test"),
-				isRootStack:         true,
-				clientMock:          describeStacksErrorMock,
-				operatorManagerMock: mockOperatorManager,
+				ctx:         context.Background(),
+				stackName:   aws.String("test"),
+				isRootStack: true,
 			},
-			want:    fmt.Errorf("DescribeStacksError"),
-			wantErr: true,
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{},
+					true,
+					fmt.Errorf("DescribeStacksError"),
+				)
+			},
+			prepareMockOperatorManagerFn: func(m *MockIOperatorManager) {},
+			want:                         fmt.Errorf("DescribeStacksError"),
+			wantErr:                      true,
+		},
+		{
+			name: "delete stack failure for child stack for describe stacks error",
+			args: args{
+				ctx:         context.Background(),
+				stackName:   aws.String("test"),
+				isRootStack: false,
+			},
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{},
+					true,
+					fmt.Errorf("DescribeStacksError"),
+				)
+			},
+			prepareMockOperatorManagerFn: func(m *MockIOperatorManager) {},
+			want:                         fmt.Errorf("DescribeStacksError"),
+			wantErr:                      true,
 		},
 		{
 			name: "delete stack failure for root stack for describe stacks but not exists",
 			args: args{
-				ctx:                 context.Background(),
-				stackName:           aws.String("test"),
-				isRootStack:         true,
-				clientMock:          describeStacksNotExistsErrorMock,
-				operatorManagerMock: mockOperatorManager,
+				ctx:         context.Background(),
+				stackName:   aws.String("test"),
+				isRootStack: true,
 			},
-			want:    fmt.Errorf("NotExistsError: test stack not found."),
-			wantErr: true,
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{},
+					false,
+					nil,
+				)
+			},
+			prepareMockOperatorManagerFn: func(m *MockIOperatorManager) {},
+			want:                         fmt.Errorf("NotExistsError: test stack not found."),
+			wantErr:                      true,
 		},
 		{
-			name: "delete stack failure for root stack for list stack resources",
+			name: "delete stack failure for child stack for describe stacks but not exists",
 			args: args{
-				ctx:                 context.Background(),
-				stackName:           aws.String("test"),
-				isRootStack:         true,
-				clientMock:          listStackResourcesErrorMock,
-				operatorManagerMock: mockOperatorManager,
+				ctx:         context.Background(),
+				stackName:   aws.String("test"),
+				isRootStack: false,
 			},
-			want:    fmt.Errorf("ListStackResourcesError"),
-			wantErr: true,
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{},
+					false,
+					nil,
+				)
+			},
+			prepareMockOperatorManagerFn: func(m *MockIOperatorManager) {},
+			want:                         nil,
+			wantErr:                      false,
 		},
 		{
-			name: "delete stack failure for child stack for list stack resources",
+			name: "delete stack failure for root stack for describe stacks error after delete stack",
 			args: args{
-				ctx:                 context.Background(),
-				stackName:           aws.String("test"),
-				isRootStack:         false,
-				clientMock:          listStackResourcesErrorMock,
-				operatorManagerMock: mockOperatorManager,
+				ctx:         context.Background(),
+				stackName:   aws.String("test"),
+				isRootStack: true,
 			},
-			want:    fmt.Errorf("ListStackResourcesError"),
-			wantErr: true,
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "DELETE_FAILED",
+								EnableTerminationProtection: aws.Bool(false),
+							},
+						},
+					},
+					true,
+					nil,
+				)
+
+				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
+
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{},
+					true,
+					fmt.Errorf("DescribeStacksError"),
+				)
+			},
+			prepareMockOperatorManagerFn: func(m *MockIOperatorManager) {},
+			want:                         fmt.Errorf("DescribeStacksError"),
+			wantErr:                      true,
 		},
 		{
-			name: "delete stack failure for root stack for operator manager all errors",
+			name: "delete stack failure for child stack for describe stacks error after delete stack",
 			args: args{
-				ctx:                 context.Background(),
-				stackName:           aws.String("test"),
-				isRootStack:         true,
-				clientMock:          mock,
-				operatorManagerMock: allErrorMockOperatorManager,
+				ctx:         context.Background(),
+				stackName:   aws.String("test"),
+				isRootStack: false,
 			},
-			want:    fmt.Errorf("CheckResourceCountsError"),
-			wantErr: true,
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "DELETE_FAILED",
+								EnableTerminationProtection: aws.Bool(false),
+							},
+						},
+					},
+					true,
+					nil,
+				)
+
+				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
+
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{},
+					true,
+					fmt.Errorf("DescribeStacksError"),
+				)
+			},
+			prepareMockOperatorManagerFn: func(m *MockIOperatorManager) {},
+			want:                         fmt.Errorf("DescribeStacksError"),
+			wantErr:                      true,
 		},
 		{
-			name: "delete stack failure for child stack for operator manager all errors",
+			name: "delete stack success for root stack for no resources after delete stack",
 			args: args{
-				ctx:                 context.Background(),
-				stackName:           aws.String("test"),
-				isRootStack:         false,
-				clientMock:          mock,
-				operatorManagerMock: allErrorMockOperatorManager,
+				ctx:         context.Background(),
+				stackName:   aws.String("test"),
+				isRootStack: true,
 			},
-			want:    fmt.Errorf("CheckResourceCountsError"),
-			wantErr: true,
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "DELETE_FAILED",
+								EnableTerminationProtection: aws.Bool(false),
+							},
+						},
+					},
+					true,
+					nil,
+				)
+
+				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
+
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{},
+					false,
+					nil,
+				)
+			},
+			prepareMockOperatorManagerFn: func(m *MockIOperatorManager) {},
+			want:                         nil,
+			wantErr:                      false,
+		},
+		{
+			name: "delete stack success for child stack for no resources after delete stack",
+			args: args{
+				ctx:         context.Background(),
+				stackName:   aws.String("test"),
+				isRootStack: false,
+			},
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "DELETE_FAILED",
+								EnableTerminationProtection: aws.Bool(false),
+							},
+						},
+					},
+					true,
+					nil,
+				)
+
+				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
+
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{},
+					false,
+					nil,
+				)
+			},
+			prepareMockOperatorManagerFn: func(m *MockIOperatorManager) {},
+			want:                         nil,
+			wantErr:                      false,
+		},
+		{
+			name: "delete stack failure for root stack for list stack resources error",
+			args: args{
+				ctx:         context.Background(),
+				stackName:   aws.String("test"),
+				isRootStack: true,
+			},
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "DELETE_FAILED",
+								EnableTerminationProtection: aws.Bool(false),
+							},
+						},
+					},
+					true,
+					nil,
+				).AnyTimes()
+
+				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
+
+				m.EXPECT().ListStackResources(gomock.Any(), aws.String("test")).Return(
+					[]types.StackResourceSummary{},
+					fmt.Errorf("ListStackResourcesError"),
+				)
+			},
+			prepareMockOperatorManagerFn: func(m *MockIOperatorManager) {},
+			want:                         fmt.Errorf("ListStackResourcesError"),
+			wantErr:                      true,
+		},
+		{
+			name: "delete stack failure for child stack for list stack resources error",
+			args: args{
+				ctx:         context.Background(),
+				stackName:   aws.String("test"),
+				isRootStack: false,
+			},
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "DELETE_FAILED",
+								EnableTerminationProtection: aws.Bool(false),
+							},
+						},
+					},
+					true,
+					nil,
+				).AnyTimes()
+
+				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
+
+				m.EXPECT().ListStackResources(gomock.Any(), aws.String("test")).Return(
+					[]types.StackResourceSummary{},
+					fmt.Errorf("ListStackResourcesError"),
+				)
+			},
+			prepareMockOperatorManagerFn: func(m *MockIOperatorManager) {},
+			want:                         fmt.Errorf("ListStackResourcesError"),
+			wantErr:                      true,
 		},
 		{
-			name: "delete stack failure for root stack for operator manager check resource counts",
+			name: "delete stack failure for root stack for operator manager check resource counts error",
 			args: args{
-				ctx:                 context.Background(),
-				stackName:           aws.String("test"),
-				isRootStack:         true,
-				clientMock:          mock,
-				operatorManagerMock: checkResourceCountsErrorMockOperatorManager,
+				ctx:         context.Background(),
+				stackName:   aws.String("test"),
+				isRootStack: true,
+			},
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "DELETE_FAILED",
+								EnableTerminationProtection: aws.Bool(false),
+							},
+						},
+					},
+					true,
+					nil,
+				).AnyTimes()
+
+				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
+
+				m.EXPECT().ListStackResources(gomock.Any(), aws.String("test")).Return(
+					[]types.StackResourceSummary{
+						{
+							LogicalResourceId:  aws.String("LogicalResourceId1"),
+							ResourceStatus:     "DELETE_FAILED",
+							ResourceType:       aws.String("AWS::CloudFormation::Stack"),
+							PhysicalResourceId: aws.String("PhysicalResourceId1"),
+						},
+						{
+							LogicalResourceId:  aws.String("LogicalResourceId2"),
+							ResourceStatus:     "DELETE_FAILED",
+							ResourceType:       aws.String("AWS::S3::Bucket"),
+							PhysicalResourceId: aws.String("PhysicalResourceId2"),
+						},
+					},
+					nil,
+				)
+			},
+			prepareMockOperatorManagerFn: func(m *MockIOperatorManager) {
+				m.EXPECT().SetOperatorCollection(aws.String("test"), gomock.Any()).Do(
+					func(stackName *string, stackResourceSummaries []types.StackResourceSummary) {},
+				)
+				m.EXPECT().CheckResourceCounts().Return(fmt.Errorf("CheckResourceCountsError"))
 			},
 			want:    fmt.Errorf("CheckResourceCountsError"),
 			wantErr: true,
 		},
 		{
-			name: "delete stack failure for child stack for operator manager check resource counts",
+			name: "delete stack failure for child stack for operator manager check resource counts error",
 			args: args{
-				ctx:                 context.Background(),
-				stackName:           aws.String("test"),
-				isRootStack:         false,
-				clientMock:          mock,
-				operatorManagerMock: checkResourceCountsErrorMockOperatorManager,
+				ctx:         context.Background(),
+				stackName:   aws.String("test"),
+				isRootStack: false,
+			},
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "DELETE_FAILED",
+								EnableTerminationProtection: aws.Bool(false),
+							},
+						},
+					},
+					true,
+					nil,
+				).AnyTimes()
+
+				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
+
+				m.EXPECT().ListStackResources(gomock.Any(), aws.String("test")).Return(
+					[]types.StackResourceSummary{
+						{
+							LogicalResourceId:  aws.String("LogicalResourceId1"),
+							ResourceStatus:     "DELETE_FAILED",
+							ResourceType:       aws.String("AWS::CloudFormation::Stack"),
+							PhysicalResourceId: aws.String("PhysicalResourceId1"),
+						},
+						{
+							LogicalResourceId:  aws.String("LogicalResourceId2"),
+							ResourceStatus:     "DELETE_FAILED",
+							ResourceType:       aws.String("AWS::S3::Bucket"),
+							PhysicalResourceId: aws.String("PhysicalResourceId2"),
+						},
+					},
+					nil,
+				)
+			},
+			prepareMockOperatorManagerFn: func(m *MockIOperatorManager) {
+				m.EXPECT().SetOperatorCollection(aws.String("test"), gomock.Any()).Do(
+					func(stackName *string, stackResourceSummaries []types.StackResourceSummary) {},
+				)
+				m.EXPECT().CheckResourceCounts().Return(fmt.Errorf("CheckResourceCountsError"))
 			},
 			want:    fmt.Errorf("CheckResourceCountsError"),
 			wantErr: true,
 		},
 		{
-			name: "delete stack failure for root stack for operator manager delete resource collection",
+			name: "delete stack failure for root stack for operator manager delete resource collection error",
 			args: args{
-				ctx:                 context.Background(),
-				stackName:           aws.String("test"),
-				isRootStack:         true,
-				clientMock:          mock,
-				operatorManagerMock: deleteResourceCollectionErrorMockOperatorManager,
+				ctx:         context.Background(),
+				stackName:   aws.String("test"),
+				isRootStack: true,
+			},
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "DELETE_FAILED",
+								EnableTerminationProtection: aws.Bool(false),
+							},
+						},
+					},
+					true,
+					nil,
+				).AnyTimes()
+
+				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
+
+				m.EXPECT().ListStackResources(gomock.Any(), aws.String("test")).Return(
+					[]types.StackResourceSummary{
+						{
+							LogicalResourceId:  aws.String("LogicalResourceId1"),
+							ResourceStatus:     "DELETE_FAILED",
+							ResourceType:       aws.String("AWS::CloudFormation::Stack"),
+							PhysicalResourceId: aws.String("PhysicalResourceId1"),
+						},
+						{
+							LogicalResourceId:  aws.String("LogicalResourceId2"),
+							ResourceStatus:     "DELETE_FAILED",
+							ResourceType:       aws.String("AWS::S3::Bucket"),
+							PhysicalResourceId: aws.String("PhysicalResourceId2"),
+						},
+					},
+					nil,
+				)
+			},
+			prepareMockOperatorManagerFn: func(m *MockIOperatorManager) {
+				m.EXPECT().SetOperatorCollection(aws.String("test"), gomock.Any()).Do(
+					func(stackName *string, stackResourceSummaries []types.StackResourceSummary) {},
+				)
+				m.EXPECT().CheckResourceCounts().Return(nil)
+				m.EXPECT().DeleteResourceCollection(gomock.Any()).Return(fmt.Errorf("DeleteResourceCollectionError"))
 			},
 			want:    fmt.Errorf("DeleteResourceCollectionError"),
 			wantErr: true,
 		},
 		{
-			name: "delete stack failure for child stack for operator manager delete resource collection",
+			name: "delete stack failure for child stack for operator manager delete resource collection error",
 			args: args{
-				ctx:                 context.Background(),
-				stackName:           aws.String("test"),
-				isRootStack:         false,
-				clientMock:          mock,
-				operatorManagerMock: deleteResourceCollectionErrorMockOperatorManager,
+				ctx:         context.Background(),
+				stackName:   aws.String("test"),
+				isRootStack: false,
+			},
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "DELETE_FAILED",
+								EnableTerminationProtection: aws.Bool(false),
+							},
+						},
+					},
+					true,
+					nil,
+				).AnyTimes()
+
+				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
+
+				m.EXPECT().ListStackResources(gomock.Any(), aws.String("test")).Return(
+					[]types.StackResourceSummary{
+						{
+							LogicalResourceId:  aws.String("LogicalResourceId1"),
+							ResourceStatus:     "DELETE_FAILED",
+							ResourceType:       aws.String("AWS::CloudFormation::Stack"),
+							PhysicalResourceId: aws.String("PhysicalResourceId1"),
+						},
+						{
+							LogicalResourceId:  aws.String("LogicalResourceId2"),
+							ResourceStatus:     "DELETE_FAILED",
+							ResourceType:       aws.String("AWS::S3::Bucket"),
+							PhysicalResourceId: aws.String("PhysicalResourceId2"),
+						},
+					},
+					nil,
+				)
+			},
+			prepareMockOperatorManagerFn: func(m *MockIOperatorManager) {
+				m.EXPECT().SetOperatorCollection(aws.String("test"), gomock.Any()).Do(
+					func(stackName *string, stackResourceSummaries []types.StackResourceSummary) {},
+				)
+				m.EXPECT().CheckResourceCounts().Return(nil)
+				m.EXPECT().DeleteResourceCollection(gomock.Any()).Return(fmt.Errorf("DeleteResourceCollectionError"))
 			},
 			want:    fmt.Errorf("DeleteResourceCollectionError"),
 			wantErr: true,
 		},
+		{
+			name: "delete stack success for root stack for delete stack at last",
+			args: args{
+				ctx:         context.Background(),
+				stackName:   aws.String("test"),
+				isRootStack: true,
+			},
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "DELETE_FAILED",
+								EnableTerminationProtection: aws.Bool(false),
+							},
+						},
+					},
+					true,
+					nil,
+				).AnyTimes()
+
+				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
+
+				m.EXPECT().ListStackResources(gomock.Any(), aws.String("test")).Return(
+					[]types.StackResourceSummary{
+						{
+							LogicalResourceId:  aws.String("LogicalResourceId1"),
+							ResourceStatus:     "DELETE_FAILED",
+							ResourceType:       aws.String("AWS::CloudFormation::Stack"),
+							PhysicalResourceId: aws.String("PhysicalResourceId1"),
+						},
+						{
+							LogicalResourceId:  aws.String("LogicalResourceId2"),
+							ResourceStatus:     "DELETE_FAILED",
+							ResourceType:       aws.String("AWS::S3::Bucket"),
+							PhysicalResourceId: aws.String("PhysicalResourceId2"),
+						},
+					},
+					nil,
+				)
+
+				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{"LogicalResourceId1", "LogicalResourceId2"}).Return(nil)
+			},
+			prepareMockOperatorManagerFn: func(m *MockIOperatorManager) {
+				m.EXPECT().SetOperatorCollection(aws.String("test"), gomock.Any()).Do(
+					func(stackName *string, stackResourceSummaries []types.StackResourceSummary) {},
+				)
+				m.EXPECT().CheckResourceCounts().Return(nil)
+				m.EXPECT().DeleteResourceCollection(gomock.Any()).Return(nil)
+				m.EXPECT().GetLogicalResourceIds().Return([]string{"LogicalResourceId1", "LogicalResourceId2"})
+			},
+			want:    nil,
+			wantErr: false,
+		},
+		{
+			name: "delete stack success for child stack for delete stack at last",
+			args: args{
+				ctx:         context.Background(),
+				stackName:   aws.String("test"),
+				isRootStack: false,
+			},
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "DELETE_FAILED",
+								EnableTerminationProtection: aws.Bool(false),
+							},
+						},
+					},
+					true,
+					nil,
+				).AnyTimes()
+
+				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
+
+				m.EXPECT().ListStackResources(gomock.Any(), aws.String("test")).Return(
+					[]types.StackResourceSummary{
+						{
+							LogicalResourceId:  aws.String("LogicalResourceId1"),
+							ResourceStatus:     "DELETE_FAILED",
+							ResourceType:       aws.String("AWS::CloudFormation::Stack"),
+							PhysicalResourceId: aws.String("PhysicalResourceId1"),
+						},
+						{
+							LogicalResourceId:  aws.String("LogicalResourceId2"),
+							ResourceStatus:     "DELETE_FAILED",
+							ResourceType:       aws.String("AWS::S3::Bucket"),
+							PhysicalResourceId: aws.String("PhysicalResourceId2"),
+						},
+					},
+					nil,
+				)
+
+				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{"LogicalResourceId1", "LogicalResourceId2"}).Return(nil)
+			},
+			prepareMockOperatorManagerFn: func(m *MockIOperatorManager) {
+				m.EXPECT().SetOperatorCollection(aws.String("test"), gomock.Any()).Do(
+					func(stackName *string, stackResourceSummaries []types.StackResourceSummary) {},
+				)
+				m.EXPECT().CheckResourceCounts().Return(nil)
+				m.EXPECT().DeleteResourceCollection(gomock.Any()).Return(nil)
+				m.EXPECT().GetLogicalResourceIds().Return([]string{"LogicalResourceId1", "LogicalResourceId2"})
+			},
+			want:    nil,
+			wantErr: false,
+		},
+		{
+			name: "delete stack failure for root stack for delete stack error at last",
+			args: args{
+				ctx:         context.Background(),
+				stackName:   aws.String("test"),
+				isRootStack: true,
+			},
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "DELETE_FAILED",
+								EnableTerminationProtection: aws.Bool(false),
+							},
+						},
+					},
+					true,
+					nil,
+				).AnyTimes()
+
+				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
+
+				m.EXPECT().ListStackResources(gomock.Any(), aws.String("test")).Return(
+					[]types.StackResourceSummary{
+						{
+							LogicalResourceId:  aws.String("LogicalResourceId1"),
+							ResourceStatus:     "DELETE_FAILED",
+							ResourceType:       aws.String("AWS::CloudFormation::Stack"),
+							PhysicalResourceId: aws.String("PhysicalResourceId1"),
+						},
+						{
+							LogicalResourceId:  aws.String("LogicalResourceId2"),
+							ResourceStatus:     "DELETE_FAILED",
+							ResourceType:       aws.String("AWS::S3::Bucket"),
+							PhysicalResourceId: aws.String("PhysicalResourceId2"),
+						},
+					},
+					nil,
+				)
+
+				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{"LogicalResourceId1", "LogicalResourceId2"}).Return(fmt.Errorf("DeleteStackError"))
+			},
+			prepareMockOperatorManagerFn: func(m *MockIOperatorManager) {
+				m.EXPECT().SetOperatorCollection(aws.String("test"), gomock.Any()).Do(
+					func(stackName *string, stackResourceSummaries []types.StackResourceSummary) {},
+				)
+				m.EXPECT().CheckResourceCounts().Return(nil)
+				m.EXPECT().DeleteResourceCollection(gomock.Any()).Return(nil)
+				m.EXPECT().GetLogicalResourceIds().Return([]string{"LogicalResourceId1", "LogicalResourceId2"})
+			},
+			want:    fmt.Errorf("DeleteStackError"),
+			wantErr: true,
+		},
+		{
+			name: "delete stack failure for child stack for delete stack error at last",
+			args: args{
+				ctx:         context.Background(),
+				stackName:   aws.String("test"),
+				isRootStack: false,
+			},
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "DELETE_FAILED",
+								EnableTerminationProtection: aws.Bool(false),
+							},
+						},
+					},
+					true,
+					nil,
+				).AnyTimes()
+
+				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
+
+				m.EXPECT().ListStackResources(gomock.Any(), aws.String("test")).Return(
+					[]types.StackResourceSummary{
+						{
+							LogicalResourceId:  aws.String("LogicalResourceId1"),
+							ResourceStatus:     "DELETE_FAILED",
+							ResourceType:       aws.String("AWS::CloudFormation::Stack"),
+							PhysicalResourceId: aws.String("PhysicalResourceId1"),
+						},
+						{
+							LogicalResourceId:  aws.String("LogicalResourceId2"),
+							ResourceStatus:     "DELETE_FAILED",
+							ResourceType:       aws.String("AWS::S3::Bucket"),
+							PhysicalResourceId: aws.String("PhysicalResourceId2"),
+						},
+					},
+					nil,
+				)
+
+				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{"LogicalResourceId1", "LogicalResourceId2"}).Return(fmt.Errorf("DeleteStackError"))
+			},
+			prepareMockOperatorManagerFn: func(m *MockIOperatorManager) {
+				m.EXPECT().SetOperatorCollection(aws.String("test"), gomock.Any()).Do(
+					func(stackName *string, stackResourceSummaries []types.StackResourceSummary) {},
+				)
+				m.EXPECT().CheckResourceCounts().Return(nil)
+				m.EXPECT().DeleteResourceCollection(gomock.Any()).Return(nil)
+				m.EXPECT().GetLogicalResourceIds().Return([]string{"LogicalResourceId1", "LogicalResourceId2"})
+			},
+			want:    fmt.Errorf("DeleteStackError"),
+			wantErr: true,
+		},
 	}
 
 	for _, tt := range cases {
 		t.Run(tt.name, func(t *testing.T) {
+			ctrl := gomock.NewController(t)
+			cloudformationMock := client.NewMockICloudFormation(ctrl)
+			operatorManagerMock := NewMockIOperatorManager(ctrl)
+
+			tt.prepareMockCloudFormationFn(cloudformationMock)
+			tt.prepareMockOperatorManagerFn(operatorManagerMock)
+
 			targetResourceTypes := []string{
 				"AWS::S3::Bucket",
 				"AWS::IAM::Role",
@@ -274,9 +1002,10 @@ func TestCloudFormationStackOperator_DeleteCloudFormationStack(t *testing.T) {
 				"AWS::CloudFormation::Stack",
 				"Custom::",
 			}
-			cloudformationStackOperator := NewCloudFormationStackOperator(aws.Config{}, tt.args.clientMock, targetResourceTypes)
 
-			err := cloudformationStackOperator.DeleteCloudFormationStack(tt.args.ctx, tt.args.stackName, tt.args.isRootStack, tt.args.operatorManagerMock)
+			cloudformationStackOperator := NewCloudFormationStackOperator(aws.Config{}, cloudformationMock, targetResourceTypes)
+
+			err := cloudformationStackOperator.DeleteCloudFormationStack(tt.args.ctx, tt.args.stackName, tt.args.isRootStack, operatorManagerMock)
 			if (err != nil) != tt.wantErr {
 				t.Errorf("error = %#v, wantErr %#v", err.Error(), tt.wantErr)
 				return
@@ -289,21 +1018,13 @@ func TestCloudFormationStackOperator_DeleteCloudFormationStack(t *testing.T) {
 	}
 }
 
-func TestCloudFormationStackOperator_deleteRootStack(t *testing.T) {
+func TestCloudFormationStackOperator_deleteStackNormally(t *testing.T) {
 	io.NewLogger(false)
 
-	mock := client.NewMockCloudFormation()
-	terminationProtectionIsEnabledMock := client.NewTerminationProtectionIsEnabledMockCloudFormation()
-	notDeleteFailedMock := client.NewNotDeleteFailedMockCloudFormation()
-	allErrorMock := client.NewAllErrorMockCloudFormation()
-	describeStacksErrorMock := client.NewDescribeStacksErrorMockCloudFormation()
-	describeStacksNotExistsErrorMock := client.NewDescribeStacksNotExistsErrorMockCloudFormation()
-
 	type args struct {
 		ctx         context.Context
 		stackName   *string
 		isRootStack bool
-		clientMock  client.ICloudFormation
 	}
 
 	type want struct {
@@ -312,10 +1033,11 @@ func TestCloudFormationStackOperator_deleteRootStack(t *testing.T) {
 	}
 
 	cases := []struct {
-		name    string
-		args    args
-		want    want
-		wantErr bool
+		name                        string
+		args                        args
+		prepareMockCloudFormationFn func(m *client.MockICloudFormation)
+		want                        want
+		wantErr                     bool
 	}{
 		{
 			name: "delete stack successfully for root stack",
@@ -323,7 +1045,81 @@ func TestCloudFormationStackOperator_deleteRootStack(t *testing.T) {
 				ctx:         context.Background(),
 				stackName:   aws.String("test"),
 				isRootStack: true,
-				clientMock:  mock,
+			},
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "DELETE_FAILED",
+								EnableTerminationProtection: aws.Bool(false),
+							},
+						},
+					},
+					true,
+					nil,
+				)
+
+				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
+
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "DELETE_FAILED",
+								EnableTerminationProtection: aws.Bool(false),
+							},
+						},
+					},
+					true,
+					nil,
+				)
+			},
+			want: want{
+				got: false,
+				err: nil,
+			},
+			wantErr: false,
+		},
+		{
+			name: "delete stack successfully for child stack",
+			args: args{
+				ctx:         context.Background(),
+				stackName:   aws.String("test"),
+				isRootStack: false,
+			},
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "DELETE_FAILED",
+								EnableTerminationProtection: aws.Bool(false),
+							},
+						},
+					},
+					true,
+					nil,
+				)
+
+				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
+
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "DELETE_FAILED",
+								EnableTerminationProtection: aws.Bool(false),
+							},
+						},
+					},
+					true,
+					nil,
+				)
 			},
 			want: want{
 				got: false,
@@ -337,7 +1133,49 @@ func TestCloudFormationStackOperator_deleteRootStack(t *testing.T) {
 				ctx:         context.Background(),
 				stackName:   aws.String("test"),
 				isRootStack: true,
-				clientMock:  terminationProtectionIsEnabledMock,
+			},
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "CREATE_COMPLETE",
+								EnableTerminationProtection: aws.Bool(true),
+							},
+						},
+					},
+					true,
+					nil,
+				)
+			},
+			want: want{
+				got: false,
+				err: fmt.Errorf("TerminationProtectionIsEnabled: test"),
+			},
+			wantErr: true,
+		},
+		{
+			name: "delete stack failure for child stack for TerminationProtection is enabled stack",
+			args: args{
+				ctx:         context.Background(),
+				stackName:   aws.String("test"),
+				isRootStack: false,
+			},
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "CREATE_COMPLETE",
+								EnableTerminationProtection: aws.Bool(true),
+							},
+						},
+					},
+					true,
+					nil,
+				)
 			},
 			want: want{
 				got: false,
@@ -351,7 +1189,23 @@ func TestCloudFormationStackOperator_deleteRootStack(t *testing.T) {
 				ctx:         context.Background(),
 				stackName:   aws.String("test"),
 				isRootStack: true,
-				clientMock:  notDeleteFailedMock,
+			},
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "UPDATE_ROLLBACK_COMPLETE",
+								EnableTerminationProtection: aws.Bool(false),
+							},
+						},
+					},
+					true,
+					nil,
+				).AnyTimes()
+
+				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
 			},
 			want: want{
 				got: false,
@@ -360,96 +1214,204 @@ func TestCloudFormationStackOperator_deleteRootStack(t *testing.T) {
 			wantErr: true,
 		},
 		{
-			name: "delete stack failure for root stack for all errors",
+			name: "delete stack failure for child stack for not DELETE_FAILED stack",
 			args: args{
 				ctx:         context.Background(),
 				stackName:   aws.String("test"),
-				isRootStack: true,
-				clientMock:  allErrorMock,
+				isRootStack: false,
+			},
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "UPDATE_ROLLBACK_COMPLETE",
+								EnableTerminationProtection: aws.Bool(false),
+							},
+						},
+					},
+					true,
+					nil,
+				).AnyTimes()
+
+				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
 			},
 			want: want{
 				got: false,
-				err: fmt.Errorf("DescribeStacksError"),
+				err: fmt.Errorf("StackStatusError: StackStatus is expected to be DELETE_FAILED, but UPDATE_ROLLBACK_COMPLETE: test"),
 			},
 			wantErr: true,
 		},
 		{
-			name: "delete stack failure for root stack for describe stacks",
+			name: "delete stack failure for root stack for delete stack error",
 			args: args{
 				ctx:         context.Background(),
 				stackName:   aws.String("test"),
 				isRootStack: true,
-				clientMock:  describeStacksErrorMock,
+			},
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "DELETE_FAILED",
+								EnableTerminationProtection: aws.Bool(false),
+							},
+						},
+					},
+					true,
+					nil,
+				)
+
+				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(fmt.Errorf("DeleteStackError"))
 			},
 			want: want{
 				got: false,
-				err: fmt.Errorf("DescribeStacksError"),
+				err: fmt.Errorf("DeleteStackError"),
 			},
 			wantErr: true,
 		},
 		{
-			name: "delete stack failure for root stack for describe stacks but not exists",
+			name: "delete stack failure for child stack for delete stack error",
 			args: args{
 				ctx:         context.Background(),
 				stackName:   aws.String("test"),
-				isRootStack: true,
-				clientMock:  describeStacksNotExistsErrorMock,
+				isRootStack: false,
+			},
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "DELETE_FAILED",
+								EnableTerminationProtection: aws.Bool(false),
+							},
+						},
+					},
+					true,
+					nil,
+				)
+
+				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(fmt.Errorf("DeleteStackError"))
 			},
 			want: want{
 				got: false,
-				err: fmt.Errorf("NotExistsError: test stack not found."),
+				err: fmt.Errorf("DeleteStackError"),
 			},
 			wantErr: true,
 		},
 		{
-			name: "delete stack successfully for child stack",
+			name: "delete stack failure for root stack for describe stacks error",
 			args: args{
 				ctx:         context.Background(),
 				stackName:   aws.String("test"),
-				isRootStack: false,
-				clientMock:  mock,
+				isRootStack: true,
+			},
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{},
+					true,
+					fmt.Errorf("DescribeStacksError"),
+				)
 			},
 			want: want{
 				got: false,
-				err: nil,
+				err: fmt.Errorf("DescribeStacksError"),
 			},
-			wantErr: false,
+			wantErr: true,
 		},
 		{
-			name: "delete stack failure for child stack for TerminationProtection is enabled stack",
+			name: "delete stack failure for child stack for describe stacks error",
 			args: args{
 				ctx:         context.Background(),
 				stackName:   aws.String("test"),
 				isRootStack: false,
-				clientMock:  terminationProtectionIsEnabledMock,
+			},
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{},
+					true,
+					fmt.Errorf("DescribeStacksError"),
+				)
 			},
 			want: want{
 				got: false,
-				err: fmt.Errorf("TerminationProtectionIsEnabled: test"),
+				err: fmt.Errorf("DescribeStacksError"),
 			},
 			wantErr: true,
 		},
 		{
-			name: "delete stack failure for child stack for not DELETE_FAILED stack",
+			name: "delete stack failure for root stack for describe stacks but not exists",
 			args: args{
 				ctx:         context.Background(),
 				stackName:   aws.String("test"),
-				isRootStack: false,
-				clientMock:  notDeleteFailedMock,
+				isRootStack: true,
+			},
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{},
+					false,
+					nil,
+				)
 			},
 			want: want{
 				got: false,
-				err: fmt.Errorf("StackStatusError: StackStatus is expected to be DELETE_FAILED, but UPDATE_ROLLBACK_COMPLETE: test"),
+				err: fmt.Errorf("NotExistsError: test stack not found."),
 			},
 			wantErr: true,
 		},
 		{
-			name: "delete stack failure for child stack for all errors",
+			name: "delete stack failure for child stack for already deleted",
 			args: args{
 				ctx:         context.Background(),
 				stackName:   aws.String("test"),
 				isRootStack: false,
-				clientMock:  allErrorMock,
+			},
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{},
+					false,
+					nil,
+				)
+			},
+			want: want{
+				got: true,
+				err: nil,
+			},
+			wantErr: false,
+		},
+		{
+			name: "delete stack failure for root stack for describe stacks error after delete stack",
+			args: args{
+				ctx:         context.Background(),
+				stackName:   aws.String("test"),
+				isRootStack: true,
+			},
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "DELETE_FAILED",
+								EnableTerminationProtection: aws.Bool(false),
+							},
+						},
+					},
+					true,
+					nil,
+				)
+
+				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
+
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{},
+					true,
+					fmt.Errorf("DescribeStacksError"),
+				)
 			},
 			want: want{
 				got: false,
@@ -458,12 +1420,34 @@ func TestCloudFormationStackOperator_deleteRootStack(t *testing.T) {
 			wantErr: true,
 		},
 		{
-			name: "delete stack failure for child stack for describe stacks",
+			name: "delete stack failure for child stack for describe stacks error after delete stack",
 			args: args{
 				ctx:         context.Background(),
 				stackName:   aws.String("test"),
 				isRootStack: false,
-				clientMock:  describeStacksErrorMock,
+			},
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "DELETE_FAILED",
+								EnableTerminationProtection: aws.Bool(false),
+							},
+						},
+					},
+					true,
+					nil,
+				)
+
+				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
+
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{},
+					true,
+					fmt.Errorf("DescribeStacksError"),
+				)
 			},
 			want: want{
 				got: false,
@@ -472,12 +1456,70 @@ func TestCloudFormationStackOperator_deleteRootStack(t *testing.T) {
 			wantErr: true,
 		},
 		{
-			name: "delete stack successfully for child stack for the stack already deleted",
+			name: "delete stack success for root stack for no resources after delete stack",
+			args: args{
+				ctx:         context.Background(),
+				stackName:   aws.String("test"),
+				isRootStack: true,
+			},
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "DELETE_FAILED",
+								EnableTerminationProtection: aws.Bool(false),
+							},
+						},
+					},
+					true,
+					nil,
+				)
+
+				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
+
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{},
+					false,
+					nil,
+				)
+			},
+			want: want{
+				got: true,
+				err: nil,
+			},
+			wantErr: false,
+		},
+		{
+			name: "delete stack success for child stack for no resources after delete stack",
 			args: args{
 				ctx:         context.Background(),
 				stackName:   aws.String("test"),
 				isRootStack: false,
-				clientMock:  describeStacksNotExistsErrorMock,
+			},
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{
+						Stacks: []types.Stack{
+							{
+								StackName:                   aws.String("test"),
+								StackStatus:                 "DELETE_FAILED",
+								EnableTerminationProtection: aws.Bool(false),
+							},
+						},
+					},
+					true,
+					nil,
+				)
+
+				m.EXPECT().DeleteStack(gomock.Any(), aws.String("test"), []string{}).Return(nil)
+
+				m.EXPECT().DescribeStacks(gomock.Any(), aws.String("test")).Return(
+					&cloudformation.DescribeStacksOutput{},
+					false,
+					nil,
+				)
 			},
 			want: want{
 				got: true,
@@ -489,6 +1531,11 @@ func TestCloudFormationStackOperator_deleteRootStack(t *testing.T) {
 
 	for _, tt := range cases {
 		t.Run(tt.name, func(t *testing.T) {
+			ctrl := gomock.NewController(t)
+			cloudformationMock := client.NewMockICloudFormation(ctrl)
+
+			tt.prepareMockCloudFormationFn(cloudformationMock)
+
 			targetResourceTypes := []string{
 				"AWS::S3::Bucket",
 				"AWS::IAM::Role",
@@ -497,7 +1544,7 @@ func TestCloudFormationStackOperator_deleteRootStack(t *testing.T) {
 				"AWS::CloudFormation::Stack",
 				"Custom::",
 			}
-			cloudformationStackOperator := NewCloudFormationStackOperator(aws.Config{}, tt.args.clientMock, targetResourceTypes)
+			cloudformationStackOperator := NewCloudFormationStackOperator(aws.Config{}, cloudformationMock, targetResourceTypes)
 
 			got, err := cloudformationStackOperator.deleteStackNormally(tt.args.ctx, tt.args.stackName, tt.args.isRootStack)
 			if (err != nil) != tt.wantErr {
@@ -519,15 +1566,9 @@ func TestCloudFormationStackOperator_ListStacksFilteredByKeyword(t *testing.T) {
 	io.NewLogger(false)
 	ctx := context.Background()
 
-	mock := client.NewMockCloudFormation()
-	allErrorMock := client.NewAllErrorMockCloudFormation()
-	listStacksErrorMock := client.NewListStacksErrorMockCloudFormation()
-	listStacksEmptyMock := client.NewListStacksEmptyMockCloudFormation()
-
 	type args struct {
-		ctx        context.Context
-		keyword    string
-		clientMock client.ICloudFormation
+		ctx     context.Context
+		keyword string
 	}
 
 	type want struct {
@@ -536,17 +1577,32 @@ func TestCloudFormationStackOperator_ListStacksFilteredByKeyword(t *testing.T) {
 	}
 
 	cases := []struct {
-		name    string
-		args    args
-		want    want
-		wantErr bool
+		name                        string
+		args                        args
+		prepareMockCloudFormationFn func(m *client.MockICloudFormation)
+		want                        want
+		wantErr                     bool
 	}{
 		{
 			name: "list stacks filtered by keyword successfully",
 			args: args{
-				ctx:        ctx,
-				keyword:    "TestStack",
-				clientMock: mock,
+				ctx:     ctx,
+				keyword: "TestStack",
+			},
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().ListStacks(gomock.Any()).Return(
+					[]types.StackSummary{
+						{
+							StackName:   aws.String("TestStack1"),
+							StackStatus: types.StackStatusCreateComplete,
+						},
+						{
+							StackName:   aws.String("TestStack2"),
+							StackStatus: types.StackStatusCreateComplete,
+						},
+					},
+					nil,
+				)
 			},
 			want: want{
 				filteredStacks: []string{
@@ -560,9 +1616,23 @@ func TestCloudFormationStackOperator_ListStacksFilteredByKeyword(t *testing.T) {
 		{
 			name: "list stacks filtered by keyword but empty keyword successfully",
 			args: args{
-				ctx:        ctx,
-				keyword:    "",
-				clientMock: mock,
+				ctx:     ctx,
+				keyword: "",
+			},
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().ListStacks(gomock.Any()).Return(
+					[]types.StackSummary{
+						{
+							StackName:   aws.String("TestStack1"),
+							StackStatus: types.StackStatusCreateComplete,
+						},
+						{
+							StackName:   aws.String("TestStack2"),
+							StackStatus: types.StackStatusCreateComplete,
+						},
+					},
+					nil,
+				)
 			},
 			want: want{
 				filteredStacks: []string{
@@ -576,9 +1646,11 @@ func TestCloudFormationStackOperator_ListStacksFilteredByKeyword(t *testing.T) {
 		{
 			name: "list stacks filtered by keyword but no stacks found successfully",
 			args: args{
-				ctx:        ctx,
-				keyword:    "TestStack",
-				clientMock: listStacksEmptyMock,
+				ctx:     ctx,
+				keyword: "TestStack",
+			},
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().ListStacks(gomock.Any()).Return([]types.StackSummary{}, nil)
 			},
 			want: want{
 				filteredStacks: []string{},
@@ -589,9 +1661,11 @@ func TestCloudFormationStackOperator_ListStacksFilteredByKeyword(t *testing.T) {
 		{
 			name: "list stacks filtered by keyword but empty keyword and no stacks found successfully",
 			args: args{
-				ctx:        ctx,
-				keyword:    "",
-				clientMock: listStacksEmptyMock,
+				ctx:     ctx,
+				keyword: "",
+			},
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().ListStacks(gomock.Any()).Return([]types.StackSummary{}, nil)
 			},
 			want: want{
 				filteredStacks: []string{},
@@ -599,38 +1673,14 @@ func TestCloudFormationStackOperator_ListStacksFilteredByKeyword(t *testing.T) {
 			},
 			wantErr: false,
 		},
-		{
-			name: "list stacks filtered by keyword failure for all errors",
-			args: args{
-				ctx:        ctx,
-				keyword:    "TestStack",
-				clientMock: allErrorMock,
-			},
-			want: want{
-				filteredStacks: []string{},
-				err:            fmt.Errorf("ListStacksError"),
-			},
-			wantErr: true,
-		},
 		{
 			name: "list stacks filtered by keyword failure for list stacks errors",
 			args: args{
-				ctx:        ctx,
-				keyword:    "TestStack",
-				clientMock: listStacksErrorMock,
+				ctx:     ctx,
+				keyword: "TestStack",
 			},
-			want: want{
-				filteredStacks: []string{},
-				err:            fmt.Errorf("ListStacksError"),
-			},
-			wantErr: true,
-		},
-		{
-			name: "list stacks filtered by keyword but empty keyword failure for all errors",
-			args: args{
-				ctx:        ctx,
-				keyword:    "",
-				clientMock: allErrorMock,
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().ListStacks(gomock.Any()).Return([]types.StackSummary{}, fmt.Errorf("ListStacksError"))
 			},
 			want: want{
 				filteredStacks: []string{},
@@ -641,9 +1691,11 @@ func TestCloudFormationStackOperator_ListStacksFilteredByKeyword(t *testing.T) {
 		{
 			name: "list stacks filtered by keyword but empty keyword failure for list stacks errors",
 			args: args{
-				ctx:        ctx,
-				keyword:    "",
-				clientMock: listStacksErrorMock,
+				ctx:     ctx,
+				keyword: "",
+			},
+			prepareMockCloudFormationFn: func(m *client.MockICloudFormation) {
+				m.EXPECT().ListStacks(gomock.Any()).Return([]types.StackSummary{}, fmt.Errorf("ListStacksError"))
 			},
 			want: want{
 				filteredStacks: []string{},
@@ -655,6 +1707,11 @@ func TestCloudFormationStackOperator_ListStacksFilteredByKeyword(t *testing.T) {
 
 	for _, tt := range cases {
 		t.Run(tt.name, func(t *testing.T) {
+			ctrl := gomock.NewController(t)
+			cloudformationMock := client.NewMockICloudFormation(ctrl)
+
+			tt.prepareMockCloudFormationFn(cloudformationMock)
+
 			targetResourceTypes := []string{
 				"AWS::S3::Bucket",
 				"AWS::IAM::Role",
@@ -664,7 +1721,7 @@ func TestCloudFormationStackOperator_ListStacksFilteredByKeyword(t *testing.T) {
 				"Custom::",
 			}
 
-			cloudformationStackOperator := NewCloudFormationStackOperator(aws.Config{}, tt.args.clientMock, targetResourceTypes)
+			cloudformationStackOperator := NewCloudFormationStackOperator(aws.Config{}, cloudformationMock, targetResourceTypes)
 
 			output, err := cloudformationStackOperator.ListStacksFilteredByKeyword(tt.args.ctx, &tt.args.keyword)
 			if (err != nil) != tt.wantErr {
diff --git a/internal/operation/ecr_repository_test.go b/internal/operation/ecr_repository_test.go
index d0ae5ac..648599c 100644
--- a/internal/operation/ecr_repository_test.go
+++ b/internal/operation/ecr_repository_test.go
@@ -9,6 +9,7 @@ import (
 	cfnTypes "github.com/aws/aws-sdk-go-v2/service/cloudformation/types"
 	"github.com/go-to-k/delstack/internal/io"
 	"github.com/go-to-k/delstack/pkg/client"
+	gomock "github.com/golang/mock/gomock"
 )
 
 /*
@@ -17,29 +18,28 @@ import (
 
 func TestEcrRepositoryOperator_DeleteEcrRepository(t *testing.T) {
 	io.NewLogger(false)
-	mock := client.NewMockEcr()
-	DeleteRepositoryErrorMock := client.NewDeleteRepositoryErrorMockEcr()
-	checkEcrExistsErrorMock := client.NewCheckEcrExistsErrorMockEcr()
-	checkEcrNotExistsMock := client.NewCheckEcrNotExistsMockEcr()
 
 	type args struct {
 		ctx            context.Context
 		repositoryName *string
-		client         client.IEcr
 	}
 
 	cases := []struct {
-		name    string
-		args    args
-		want    error
-		wantErr bool
+		name          string
+		args          args
+		prepareMockFn func(m *client.MockIEcr)
+		want          error
+		wantErr       bool
 	}{
 		{
 			name: "delete ecr repository successfully",
 			args: args{
 				ctx:            context.Background(),
 				repositoryName: aws.String("test"),
-				client:         mock,
+			},
+			prepareMockFn: func(m *client.MockIEcr) {
+				m.EXPECT().CheckEcrExists(gomock.Any(), aws.String("test")).Return(true, nil)
+				m.EXPECT().DeleteRepository(gomock.Any(), aws.String("test")).Return(nil)
 			},
 			want:    nil,
 			wantErr: false,
@@ -49,7 +49,10 @@ func TestEcrRepositoryOperator_DeleteEcrRepository(t *testing.T) {
 			args: args{
 				ctx:            context.Background(),
 				repositoryName: aws.String("test"),
-				client:         DeleteRepositoryErrorMock,
+			},
+			prepareMockFn: func(m *client.MockIEcr) {
+				m.EXPECT().CheckEcrExists(gomock.Any(), aws.String("test")).Return(true, nil)
+				m.EXPECT().DeleteRepository(gomock.Any(), aws.String("test")).Return(fmt.Errorf("DeleteRepositoryError"))
 			},
 			want:    fmt.Errorf("DeleteRepositoryError"),
 			wantErr: true,
@@ -59,7 +62,9 @@ func TestEcrRepositoryOperator_DeleteEcrRepository(t *testing.T) {
 			args: args{
 				ctx:            context.Background(),
 				repositoryName: aws.String("test"),
-				client:         checkEcrExistsErrorMock,
+			},
+			prepareMockFn: func(m *client.MockIEcr) {
+				m.EXPECT().CheckEcrExists(gomock.Any(), aws.String("test")).Return(false, fmt.Errorf("DescribeRepositoriesError"))
 			},
 			want:    fmt.Errorf("DescribeRepositoriesError"),
 			wantErr: true,
@@ -69,7 +74,9 @@ func TestEcrRepositoryOperator_DeleteEcrRepository(t *testing.T) {
 			args: args{
 				ctx:            context.Background(),
 				repositoryName: aws.String("test"),
-				client:         checkEcrNotExistsMock,
+			},
+			prepareMockFn: func(m *client.MockIEcr) {
+				m.EXPECT().CheckEcrExists(gomock.Any(), aws.String("test")).Return(false, nil)
 			},
 			want:    nil,
 			wantErr: false,
@@ -78,7 +85,11 @@ func TestEcrRepositoryOperator_DeleteEcrRepository(t *testing.T) {
 
 	for _, tt := range cases {
 		t.Run(tt.name, func(t *testing.T) {
-			ecrRepositoryOperator := NewEcrRepositoryOperator(tt.args.client)
+			ctrl := gomock.NewController(t)
+			ecrMock := client.NewMockIEcr(ctrl)
+			tt.prepareMockFn(ecrMock)
+
+			ecrRepositoryOperator := NewEcrRepositoryOperator(ecrMock)
 
 			err := ecrRepositoryOperator.DeleteEcrRepository(tt.args.ctx, tt.args.repositoryName)
 			if (err != nil) != tt.wantErr {
@@ -95,25 +106,26 @@ func TestEcrRepositoryOperator_DeleteEcrRepository(t *testing.T) {
 
 func TestEcrRepositoryOperator_DeleteResourcesForEcrRepository(t *testing.T) {
 	io.NewLogger(false)
-	mock := client.NewMockEcr()
-	errorMock := client.NewDeleteRepositoryErrorMockEcr()
 
 	type args struct {
-		ctx    context.Context
-		client client.IEcr
+		ctx context.Context
 	}
 
 	cases := []struct {
-		name    string
-		args    args
-		want    error
-		wantErr bool
+		name          string
+		args          args
+		prepareMockFn func(m *client.MockIEcr)
+		want          error
+		wantErr       bool
 	}{
 		{
 			name: "delete resources successfully",
 			args: args{
-				ctx:    context.Background(),
-				client: mock,
+				ctx: context.Background(),
+			},
+			prepareMockFn: func(m *client.MockIEcr) {
+				m.EXPECT().CheckEcrExists(gomock.Any(), aws.String("PhysicalResourceId1")).Return(true, nil)
+				m.EXPECT().DeleteRepository(gomock.Any(), aws.String("PhysicalResourceId1")).Return(nil)
 			},
 			want:    nil,
 			wantErr: false,
@@ -121,17 +133,23 @@ func TestEcrRepositoryOperator_DeleteResourcesForEcrRepository(t *testing.T) {
 		{
 			name: "delete resources failure",
 			args: args{
-				ctx:    context.Background(),
-				client: errorMock,
+				ctx: context.Background(),
 			},
-			want:    fmt.Errorf("DeleteRepositoryError"),
+			prepareMockFn: func(m *client.MockIEcr) {
+				m.EXPECT().CheckEcrExists(gomock.Any(), aws.String("PhysicalResourceId1")).Return(false, fmt.Errorf("DescribeRepositoriesError"))
+			},
+			want:    fmt.Errorf("DescribeRepositoriesError"),
 			wantErr: true,
 		},
 	}
 
 	for _, tt := range cases {
 		t.Run(tt.name, func(t *testing.T) {
-			ecrRepositoryOperator := NewEcrRepositoryOperator(tt.args.client)
+			ctrl := gomock.NewController(t)
+			ecrMock := client.NewMockIEcr(ctrl)
+			tt.prepareMockFn(ecrMock)
+
+			ecrRepositoryOperator := NewEcrRepositoryOperator(ecrMock)
 			ecrRepositoryOperator.AddResource(&cfnTypes.StackResourceSummary{
 				LogicalResourceId:  aws.String("LogicalResourceId1"),
 				ResourceStatus:     "DELETE_FAILED",
diff --git a/internal/operation/iam_role_test.go b/internal/operation/iam_role_test.go
index 4376ca5..d7d44d6 100644
--- a/internal/operation/iam_role_test.go
+++ b/internal/operation/iam_role_test.go
@@ -7,8 +7,10 @@ import (
 
 	"github.com/aws/aws-sdk-go-v2/aws"
 	cfnTypes "github.com/aws/aws-sdk-go-v2/service/cloudformation/types"
+	"github.com/aws/aws-sdk-go-v2/service/iam/types"
 	"github.com/go-to-k/delstack/internal/io"
 	"github.com/go-to-k/delstack/pkg/client"
+	gomock "github.com/golang/mock/gomock"
 )
 
 /*
@@ -17,53 +19,52 @@ import (
 
 func TestIamRoleOperator_DeleteIamRole(t *testing.T) {
 	io.NewLogger(false)
-	mock := client.NewMockIam()
-	allErrorMock := client.NewAllErrorMockIam()
-	deleteRoleErrorMock := client.NewDeleteRoleErrorMockIam()
-	listAttachedRolePoliciesErrorMock := client.NewListAttachedRolePoliciesErrorMockIam()
-	detachRolePoliciesErrorMock := client.NewDetachRolePoliciesErrorMockIam()
-	detachRolePoliciesErrorAfterZeroLengthMock := client.NewDetachRolePoliciesErrorAfterZeroLengthMockIam()
-	checkRoleExistsErrorMock := client.NewCheckRoleExistsErrorMockRole()
-	checkRoleNotExistsMock := client.NewCheckRoleNotExistsMockRole()
 
 	type args struct {
 		ctx      context.Context
 		roleName *string
-		client   client.IIam
 	}
 
 	cases := []struct {
-		name    string
-		args    args
-		want    error
-		wantErr bool
+		name          string
+		args          args
+		prepareMockFn func(m *client.MockIIam)
+		want          error
+		wantErr       bool
 	}{
 		{
 			name: "delete role successfully",
 			args: args{
 				ctx:      context.Background(),
 				roleName: aws.String("test"),
-				client:   mock,
+			},
+			prepareMockFn: func(m *client.MockIIam) {
+				m.EXPECT().CheckRoleExists(gomock.Any(), aws.String("test")).Return(true, nil)
+				m.EXPECT().ListAttachedRolePolicies(gomock.Any(), aws.String("test")).Return(
+					[]types.AttachedPolicy{
+						{
+							PolicyArn:  aws.String("PolicyArn1"),
+							PolicyName: aws.String("PolicyName1"),
+						},
+						{
+							PolicyArn:  aws.String("PolicyArn2"),
+							PolicyName: aws.String("PolicyName2"),
+						},
+					}, nil)
+				m.EXPECT().DetachRolePolicies(gomock.Any(), aws.String("test"), gomock.Any()).Return(nil)
+				m.EXPECT().DeleteRole(gomock.Any(), aws.String("test")).Return(nil)
 			},
 			want:    nil,
 			wantErr: false,
 		},
-		{
-			name: "delete role failure for all errors",
-			args: args{
-				ctx:      context.Background(),
-				roleName: aws.String("test"),
-				client:   allErrorMock,
-			},
-			want:    fmt.Errorf("GetRoleError"),
-			wantErr: true,
-		},
 		{
 			name: "delete role failure for check role exists errors",
 			args: args{
 				ctx:      context.Background(),
 				roleName: aws.String("test"),
-				client:   checkRoleExistsErrorMock,
+			},
+			prepareMockFn: func(m *client.MockIIam) {
+				m.EXPECT().CheckRoleExists(gomock.Any(), aws.String("test")).Return(false, fmt.Errorf("GetRoleError"))
 			},
 			want:    fmt.Errorf("GetRoleError"),
 			wantErr: true,
@@ -73,7 +74,9 @@ func TestIamRoleOperator_DeleteIamRole(t *testing.T) {
 			args: args{
 				ctx:      context.Background(),
 				roleName: aws.String("test"),
-				client:   checkRoleNotExistsMock,
+			},
+			prepareMockFn: func(m *client.MockIIam) {
+				m.EXPECT().CheckRoleExists(gomock.Any(), aws.String("test")).Return(false, nil)
 			},
 			want:    nil,
 			wantErr: false,
@@ -83,7 +86,10 @@ func TestIamRoleOperator_DeleteIamRole(t *testing.T) {
 			args: args{
 				ctx:      context.Background(),
 				roleName: aws.String("test"),
-				client:   listAttachedRolePoliciesErrorMock,
+			},
+			prepareMockFn: func(m *client.MockIIam) {
+				m.EXPECT().CheckRoleExists(gomock.Any(), aws.String("test")).Return(true, nil)
+				m.EXPECT().ListAttachedRolePolicies(gomock.Any(), aws.String("test")).Return(nil, fmt.Errorf("ListAttachedRolePoliciesError"))
 			},
 			want:    fmt.Errorf("ListAttachedRolePoliciesError"),
 			wantErr: true,
@@ -93,17 +99,35 @@ func TestIamRoleOperator_DeleteIamRole(t *testing.T) {
 			args: args{
 				ctx:      context.Background(),
 				roleName: aws.String("test"),
-				client:   detachRolePoliciesErrorMock,
+			},
+			prepareMockFn: func(m *client.MockIIam) {
+				m.EXPECT().CheckRoleExists(gomock.Any(), aws.String("test")).Return(true, nil)
+				m.EXPECT().ListAttachedRolePolicies(gomock.Any(), aws.String("test")).Return(
+					[]types.AttachedPolicy{
+						{
+							PolicyArn:  aws.String("PolicyArn1"),
+							PolicyName: aws.String("PolicyName1"),
+						},
+						{
+							PolicyArn:  aws.String("PolicyArn2"),
+							PolicyName: aws.String("PolicyName2"),
+						},
+					}, nil)
+				m.EXPECT().DetachRolePolicies(gomock.Any(), aws.String("test"), gomock.Any()).Return(fmt.Errorf("DetachRolePoliciesError"))
 			},
 			want:    fmt.Errorf("DetachRolePoliciesError"),
 			wantErr: true,
 		},
 		{
-			name: "delete role successfully for detach role errors after zero length",
+			name: "delete role successfully for ListAttachedRolePolicies with zero length",
 			args: args{
 				ctx:      context.Background(),
 				roleName: aws.String("test"),
-				client:   detachRolePoliciesErrorAfterZeroLengthMock,
+			},
+			prepareMockFn: func(m *client.MockIIam) {
+				m.EXPECT().CheckRoleExists(gomock.Any(), aws.String("test")).Return(true, nil)
+				m.EXPECT().ListAttachedRolePolicies(gomock.Any(), aws.String("test")).Return([]types.AttachedPolicy{}, nil)
+				m.EXPECT().DeleteRole(gomock.Any(), aws.String("test")).Return(nil)
 			},
 			want:    nil,
 			wantErr: false,
@@ -113,7 +137,22 @@ func TestIamRoleOperator_DeleteIamRole(t *testing.T) {
 			args: args{
 				ctx:      context.Background(),
 				roleName: aws.String("test"),
-				client:   deleteRoleErrorMock,
+			},
+			prepareMockFn: func(m *client.MockIIam) {
+				m.EXPECT().CheckRoleExists(gomock.Any(), aws.String("test")).Return(true, nil)
+				m.EXPECT().ListAttachedRolePolicies(gomock.Any(), aws.String("test")).Return(
+					[]types.AttachedPolicy{
+						{
+							PolicyArn:  aws.String("PolicyArn1"),
+							PolicyName: aws.String("PolicyName1"),
+						},
+						{
+							PolicyArn:  aws.String("PolicyArn2"),
+							PolicyName: aws.String("PolicyName2"),
+						},
+					}, nil)
+				m.EXPECT().DetachRolePolicies(gomock.Any(), aws.String("test"), gomock.Any()).Return(nil)
+				m.EXPECT().DeleteRole(gomock.Any(), aws.String("test")).Return(fmt.Errorf("DeleteRoleError"))
 			},
 			want:    fmt.Errorf("DeleteRoleError"),
 			wantErr: true,
@@ -122,7 +161,11 @@ func TestIamRoleOperator_DeleteIamRole(t *testing.T) {
 
 	for _, tt := range cases {
 		t.Run(tt.name, func(t *testing.T) {
-			iamRoleOperator := NewIamRoleOperator(tt.args.client)
+			ctrl := gomock.NewController(t)
+			iamMock := client.NewMockIIam(ctrl)
+			tt.prepareMockFn(iamMock)
+
+			iamRoleOperator := NewIamRoleOperator(iamMock)
 
 			err := iamRoleOperator.DeleteIamRole(tt.args.ctx, tt.args.roleName)
 			if (err != nil) != tt.wantErr {
@@ -139,25 +182,38 @@ func TestIamRoleOperator_DeleteIamRole(t *testing.T) {
 
 func TestIamRoleOperator_DeleteResourcesForIamRole(t *testing.T) {
 	io.NewLogger(false)
-	mock := client.NewMockIam()
-	allErrorMock := client.NewAllErrorMockIam()
 
 	type args struct {
-		ctx    context.Context
-		client client.IIam
+		ctx context.Context
 	}
 
 	cases := []struct {
-		name    string
-		args    args
-		want    error
-		wantErr bool
+		name          string
+		args          args
+		prepareMockFn func(m *client.MockIIam)
+		want          error
+		wantErr       bool
 	}{
 		{
 			name: "delete resources successfully",
 			args: args{
-				ctx:    context.Background(),
-				client: mock,
+				ctx: context.Background(),
+			},
+			prepareMockFn: func(m *client.MockIIam) {
+				m.EXPECT().CheckRoleExists(gomock.Any(), aws.String("PhysicalResourceId1")).Return(true, nil)
+				m.EXPECT().ListAttachedRolePolicies(gomock.Any(), aws.String("PhysicalResourceId1")).Return(
+					[]types.AttachedPolicy{
+						{
+							PolicyArn:  aws.String("PolicyArn1"),
+							PolicyName: aws.String("PolicyName1"),
+						},
+						{
+							PolicyArn:  aws.String("PolicyArn2"),
+							PolicyName: aws.String("PolicyName2"),
+						},
+					}, nil)
+				m.EXPECT().DetachRolePolicies(gomock.Any(), aws.String("PhysicalResourceId1"), gomock.Any()).Return(nil)
+				m.EXPECT().DeleteRole(gomock.Any(), aws.String("PhysicalResourceId1")).Return(nil)
 			},
 			want:    nil,
 			wantErr: false,
@@ -165,8 +221,10 @@ func TestIamRoleOperator_DeleteResourcesForIamRole(t *testing.T) {
 		{
 			name: "delete resources failure",
 			args: args{
-				ctx:    context.Background(),
-				client: allErrorMock,
+				ctx: context.Background(),
+			},
+			prepareMockFn: func(m *client.MockIIam) {
+				m.EXPECT().CheckRoleExists(gomock.Any(), aws.String("PhysicalResourceId1")).Return(false, fmt.Errorf("GetRoleError"))
 			},
 			want:    fmt.Errorf("GetRoleError"),
 			wantErr: true,
@@ -175,7 +233,11 @@ func TestIamRoleOperator_DeleteResourcesForIamRole(t *testing.T) {
 
 	for _, tt := range cases {
 		t.Run(tt.name, func(t *testing.T) {
-			iamRoleOperator := NewIamRoleOperator(tt.args.client)
+			ctrl := gomock.NewController(t)
+			iamMock := client.NewMockIIam(ctrl)
+			tt.prepareMockFn(iamMock)
+
+			iamRoleOperator := NewIamRoleOperator(iamMock)
 			iamRoleOperator.AddResource(&cfnTypes.StackResourceSummary{
 				LogicalResourceId:  aws.String("LogicalResourceId1"),
 				ResourceStatus:     "DELETE_FAILED",
diff --git a/internal/operation/operator_collection_test.go b/internal/operation/operator_collection_test.go
index c2b50e7..6dc8b1a 100644
--- a/internal/operation/operator_collection_test.go
+++ b/internal/operation/operator_collection_test.go
@@ -40,8 +40,14 @@ func TestOperatorCollection_SetOperatorCollection(t *testing.T) {
 	}
 
 	type want struct {
-		logicalResourceIdsLength        int
-		unsupportedStackResourcesLength int
+		logicalResourceIdsLength                   int
+		unsupportedStackResourcesLength            int
+		s3BucketOperatorResourcesLength            int
+		iamRoleOperatorResourcesLength             int
+		ecrRepositoryOperatorResourcesLength       int
+		backupVaultOperatorResourcesLength         int
+		cloudformationStackOperatorResourcesLength int
+		customOperatorResourcesLength              int
 	}
 
 	cases := []struct {
@@ -95,8 +101,14 @@ func TestOperatorCollection_SetOperatorCollection(t *testing.T) {
 				},
 			},
 			want: want{
-				logicalResourceIdsLength:        6,
-				unsupportedStackResourcesLength: 0,
+				logicalResourceIdsLength:                   6,
+				unsupportedStackResourcesLength:            0,
+				s3BucketOperatorResourcesLength:            1,
+				iamRoleOperatorResourcesLength:             1,
+				ecrRepositoryOperatorResourcesLength:       1,
+				backupVaultOperatorResourcesLength:         1,
+				cloudformationStackOperatorResourcesLength: 1,
+				customOperatorResourcesLength:              1,
 			},
 		},
 		{
@@ -121,8 +133,14 @@ func TestOperatorCollection_SetOperatorCollection(t *testing.T) {
 				},
 			},
 			want: want{
-				logicalResourceIdsLength:        2,
-				unsupportedStackResourcesLength: 1,
+				logicalResourceIdsLength:                   2,
+				unsupportedStackResourcesLength:            1,
+				s3BucketOperatorResourcesLength:            0,
+				iamRoleOperatorResourcesLength:             0,
+				ecrRepositoryOperatorResourcesLength:       0,
+				backupVaultOperatorResourcesLength:         0,
+				cloudformationStackOperatorResourcesLength: 1,
+				customOperatorResourcesLength:              0,
 			},
 		},
 		{
@@ -147,8 +165,14 @@ func TestOperatorCollection_SetOperatorCollection(t *testing.T) {
 				},
 			},
 			want: want{
-				logicalResourceIdsLength:        1,
-				unsupportedStackResourcesLength: 1,
+				logicalResourceIdsLength:                   1,
+				unsupportedStackResourcesLength:            1,
+				s3BucketOperatorResourcesLength:            0,
+				iamRoleOperatorResourcesLength:             0,
+				ecrRepositoryOperatorResourcesLength:       0,
+				backupVaultOperatorResourcesLength:         0,
+				cloudformationStackOperatorResourcesLength: 0,
+				customOperatorResourcesLength:              0,
 			},
 		},
 		{
@@ -173,8 +197,14 @@ func TestOperatorCollection_SetOperatorCollection(t *testing.T) {
 				},
 			},
 			want: want{
-				logicalResourceIdsLength:        1,
-				unsupportedStackResourcesLength: 0,
+				logicalResourceIdsLength:                   1,
+				unsupportedStackResourcesLength:            0,
+				s3BucketOperatorResourcesLength:            0,
+				iamRoleOperatorResourcesLength:             0,
+				ecrRepositoryOperatorResourcesLength:       0,
+				backupVaultOperatorResourcesLength:         0,
+				cloudformationStackOperatorResourcesLength: 1,
+				customOperatorResourcesLength:              0,
 			},
 		},
 		{
@@ -223,8 +253,14 @@ func TestOperatorCollection_SetOperatorCollection(t *testing.T) {
 				},
 			},
 			want: want{
-				logicalResourceIdsLength:        6,
-				unsupportedStackResourcesLength: 3,
+				logicalResourceIdsLength:                   6,
+				unsupportedStackResourcesLength:            3,
+				s3BucketOperatorResourcesLength:            1,
+				iamRoleOperatorResourcesLength:             1,
+				ecrRepositoryOperatorResourcesLength:       0,
+				backupVaultOperatorResourcesLength:         0,
+				cloudformationStackOperatorResourcesLength: 0,
+				customOperatorResourcesLength:              1,
 			},
 		},
 		{
@@ -249,8 +285,14 @@ func TestOperatorCollection_SetOperatorCollection(t *testing.T) {
 				},
 			},
 			want: want{
-				logicalResourceIdsLength:        2,
-				unsupportedStackResourcesLength: 2,
+				logicalResourceIdsLength:                   2,
+				unsupportedStackResourcesLength:            2,
+				s3BucketOperatorResourcesLength:            0,
+				iamRoleOperatorResourcesLength:             0,
+				ecrRepositoryOperatorResourcesLength:       0,
+				backupVaultOperatorResourcesLength:         0,
+				cloudformationStackOperatorResourcesLength: 0,
+				customOperatorResourcesLength:              0,
 			},
 		},
 		{
@@ -275,8 +317,14 @@ func TestOperatorCollection_SetOperatorCollection(t *testing.T) {
 				},
 			},
 			want: want{
-				logicalResourceIdsLength:        1,
-				unsupportedStackResourcesLength: 1,
+				logicalResourceIdsLength:                   1,
+				unsupportedStackResourcesLength:            1,
+				s3BucketOperatorResourcesLength:            0,
+				iamRoleOperatorResourcesLength:             0,
+				ecrRepositoryOperatorResourcesLength:       0,
+				backupVaultOperatorResourcesLength:         0,
+				cloudformationStackOperatorResourcesLength: 0,
+				customOperatorResourcesLength:              0,
 			},
 		},
 		{
@@ -301,8 +349,14 @@ func TestOperatorCollection_SetOperatorCollection(t *testing.T) {
 				},
 			},
 			want: want{
-				logicalResourceIdsLength:        1,
-				unsupportedStackResourcesLength: 1,
+				logicalResourceIdsLength:                   1,
+				unsupportedStackResourcesLength:            1,
+				s3BucketOperatorResourcesLength:            0,
+				iamRoleOperatorResourcesLength:             0,
+				ecrRepositoryOperatorResourcesLength:       0,
+				backupVaultOperatorResourcesLength:         0,
+				cloudformationStackOperatorResourcesLength: 0,
+				customOperatorResourcesLength:              0,
 			},
 		},
 		{
@@ -327,8 +381,14 @@ func TestOperatorCollection_SetOperatorCollection(t *testing.T) {
 				},
 			},
 			want: want{
-				logicalResourceIdsLength:        2,
-				unsupportedStackResourcesLength: 1,
+				logicalResourceIdsLength:                   2,
+				unsupportedStackResourcesLength:            1,
+				s3BucketOperatorResourcesLength:            1,
+				iamRoleOperatorResourcesLength:             0,
+				ecrRepositoryOperatorResourcesLength:       0,
+				backupVaultOperatorResourcesLength:         0,
+				cloudformationStackOperatorResourcesLength: 0,
+				customOperatorResourcesLength:              0,
 			},
 		},
 		{
@@ -353,8 +413,14 @@ func TestOperatorCollection_SetOperatorCollection(t *testing.T) {
 				},
 			},
 			want: want{
-				logicalResourceIdsLength:        1,
-				unsupportedStackResourcesLength: 1,
+				logicalResourceIdsLength:                   1,
+				unsupportedStackResourcesLength:            1,
+				s3BucketOperatorResourcesLength:            0,
+				iamRoleOperatorResourcesLength:             0,
+				ecrRepositoryOperatorResourcesLength:       0,
+				backupVaultOperatorResourcesLength:         0,
+				cloudformationStackOperatorResourcesLength: 0,
+				customOperatorResourcesLength:              0,
 			},
 		},
 		{
@@ -379,8 +445,14 @@ func TestOperatorCollection_SetOperatorCollection(t *testing.T) {
 				},
 			},
 			want: want{
-				logicalResourceIdsLength:        1,
-				unsupportedStackResourcesLength: 0,
+				logicalResourceIdsLength:                   1,
+				unsupportedStackResourcesLength:            0,
+				s3BucketOperatorResourcesLength:            1,
+				iamRoleOperatorResourcesLength:             0,
+				ecrRepositoryOperatorResourcesLength:       0,
+				backupVaultOperatorResourcesLength:         0,
+				cloudformationStackOperatorResourcesLength: 0,
+				customOperatorResourcesLength:              0,
 			},
 		},
 		{
@@ -405,8 +477,14 @@ func TestOperatorCollection_SetOperatorCollection(t *testing.T) {
 				},
 			},
 			want: want{
-				logicalResourceIdsLength:        2,
-				unsupportedStackResourcesLength: 1,
+				logicalResourceIdsLength:                   2,
+				unsupportedStackResourcesLength:            1,
+				s3BucketOperatorResourcesLength:            0,
+				iamRoleOperatorResourcesLength:             0,
+				ecrRepositoryOperatorResourcesLength:       0,
+				backupVaultOperatorResourcesLength:         0,
+				cloudformationStackOperatorResourcesLength: 0,
+				customOperatorResourcesLength:              1,
 			},
 		},
 		{
@@ -431,8 +509,14 @@ func TestOperatorCollection_SetOperatorCollection(t *testing.T) {
 				},
 			},
 			want: want{
-				logicalResourceIdsLength:        1,
-				unsupportedStackResourcesLength: 1,
+				logicalResourceIdsLength:                   1,
+				unsupportedStackResourcesLength:            1,
+				s3BucketOperatorResourcesLength:            0,
+				iamRoleOperatorResourcesLength:             0,
+				ecrRepositoryOperatorResourcesLength:       0,
+				backupVaultOperatorResourcesLength:         0,
+				cloudformationStackOperatorResourcesLength: 0,
+				customOperatorResourcesLength:              0,
 			},
 		},
 		{
@@ -457,8 +541,14 @@ func TestOperatorCollection_SetOperatorCollection(t *testing.T) {
 				},
 			},
 			want: want{
-				logicalResourceIdsLength:        1,
-				unsupportedStackResourcesLength: 0,
+				logicalResourceIdsLength:                   1,
+				unsupportedStackResourcesLength:            0,
+				s3BucketOperatorResourcesLength:            0,
+				iamRoleOperatorResourcesLength:             0,
+				ecrRepositoryOperatorResourcesLength:       0,
+				backupVaultOperatorResourcesLength:         0,
+				cloudformationStackOperatorResourcesLength: 0,
+				customOperatorResourcesLength:              1,
 			},
 		},
 	}
@@ -471,9 +561,40 @@ func TestOperatorCollection_SetOperatorCollection(t *testing.T) {
 
 			operatorCollection.SetOperatorCollection(tt.args.stackName, tt.args.stackResourceSummaries)
 
+			s3BucketOperatorResourcesLength := 0
+			iamRoleOperatorResourcesLength := 0
+			ecrRepositoryOperatorResourcesLength := 0
+			backupVaultOperatorResourcesLength := 0
+			cloudformationStackOperatorResourcesLength := 0
+			customOperatorResourcesLength := 0
+
+			for _, operator := range operatorCollection.GetOperators() {
+				switch operator.(type) {
+				case *S3BucketOperator:
+					s3BucketOperatorResourcesLength += operator.GetResourcesLength()
+				case *IamRoleOperator:
+					iamRoleOperatorResourcesLength += operator.GetResourcesLength()
+				case *EcrRepositoryOperator:
+					ecrRepositoryOperatorResourcesLength += operator.GetResourcesLength()
+				case *BackupVaultOperator:
+					backupVaultOperatorResourcesLength += operator.GetResourcesLength()
+				case *CloudFormationStackOperator:
+					cloudformationStackOperatorResourcesLength += operator.GetResourcesLength()
+				case *CustomOperator:
+					customOperatorResourcesLength += operator.GetResourcesLength()
+				default:
+				}
+			}
+
 			got := want{
-				logicalResourceIdsLength:        len(operatorCollection.logicalResourceIds),
-				unsupportedStackResourcesLength: len(operatorCollection.unsupportedStackResources),
+				logicalResourceIdsLength:                   len(operatorCollection.logicalResourceIds),
+				unsupportedStackResourcesLength:            len(operatorCollection.unsupportedStackResources),
+				s3BucketOperatorResourcesLength:            s3BucketOperatorResourcesLength,
+				iamRoleOperatorResourcesLength:             iamRoleOperatorResourcesLength,
+				ecrRepositoryOperatorResourcesLength:       ecrRepositoryOperatorResourcesLength,
+				backupVaultOperatorResourcesLength:         backupVaultOperatorResourcesLength,
+				cloudformationStackOperatorResourcesLength: cloudformationStackOperatorResourcesLength,
+				customOperatorResourcesLength:              customOperatorResourcesLength,
 			}
 
 			if !reflect.DeepEqual(got, tt.want) {
diff --git a/internal/operation/operator_manager_test.go b/internal/operation/operator_manager_test.go
index 08a182b..7c164dd 100644
--- a/internal/operation/operator_manager_test.go
+++ b/internal/operation/operator_manager_test.go
@@ -6,6 +6,7 @@ import (
 	"testing"
 
 	"github.com/go-to-k/delstack/internal/io"
+	gomock "github.com/golang/mock/gomock"
 )
 
 /*
@@ -15,23 +16,46 @@ import (
 func TestOperatorManager_getOperatorResourcesLength(t *testing.T) {
 	io.NewLogger(false)
 
-	mock := NewMockOperatorCollection()
-
 	type args struct {
-		ctx  context.Context
-		mock IOperatorCollection
+		ctx context.Context
 	}
 
 	cases := []struct {
-		name string
-		args args
-		want int
+		name          string
+		args          args
+		prepareMockFn func(c *gomock.Controller, m *MockIOperatorCollection)
+		want          int
 	}{
 		{
 			name: "get operator resources length successfully",
 			args: args{
-				ctx:  context.Background(),
-				mock: mock,
+				ctx: context.Background(),
+			},
+			prepareMockFn: func(c *gomock.Controller, m *MockIOperatorCollection) {
+				var operators []IOperator
+
+				cloudformationStackOperatorMock := NewMockIOperator(c)
+				s3BucketOperatorMock := NewMockIOperator(c)
+				iamRoleOperatorMock := NewMockIOperator(c)
+				ecrRepositoryOperatorMock := NewMockIOperator(c)
+				backupVaultOperatorMock := NewMockIOperator(c)
+				customOperatorMock := NewMockIOperator(c)
+
+				cloudformationStackOperatorMock.EXPECT().GetResourcesLength().Return(1)
+				s3BucketOperatorMock.EXPECT().GetResourcesLength().Return(1)
+				iamRoleOperatorMock.EXPECT().GetResourcesLength().Return(1)
+				ecrRepositoryOperatorMock.EXPECT().GetResourcesLength().Return(1)
+				backupVaultOperatorMock.EXPECT().GetResourcesLength().Return(1)
+				customOperatorMock.EXPECT().GetResourcesLength().Return(1)
+
+				operators = append(operators, cloudformationStackOperatorMock)
+				operators = append(operators, s3BucketOperatorMock)
+				operators = append(operators, iamRoleOperatorMock)
+				operators = append(operators, ecrRepositoryOperatorMock)
+				operators = append(operators, backupVaultOperatorMock)
+				operators = append(operators, customOperatorMock)
+
+				m.EXPECT().GetOperators().Return(operators)
 			},
 			want: 6,
 		},
@@ -39,7 +63,11 @@ func TestOperatorManager_getOperatorResourcesLength(t *testing.T) {
 
 	for _, tt := range cases {
 		t.Run(tt.name, func(t *testing.T) {
-			operatorManager := NewOperatorManager(tt.args.mock)
+			ctrl := gomock.NewController(t)
+			collectionMock := NewMockIOperatorCollection(ctrl)
+			tt.prepareMockFn(ctrl, collectionMock)
+
+			operatorManager := NewOperatorManager(collectionMock)
 
 			got := operatorManager.getOperatorResourcesLength()
 			if got != tt.want {
@@ -53,25 +81,58 @@ func TestOperatorManager_getOperatorResourcesLength(t *testing.T) {
 func TestOperatorManager_CheckResourceCounts(t *testing.T) {
 	io.NewLogger(false)
 
-	mock := NewMockOperatorCollection()
-	incorrectResourceCountsMock := NewIncorrectResourceCountsMockOperatorCollection()
-
 	type args struct {
-		ctx  context.Context
-		mock IOperatorCollection
+		ctx context.Context
 	}
 
 	cases := []struct {
-		name    string
-		args    args
-		want    error
-		wantErr bool
+		name          string
+		args          args
+		prepareMockFn func(c *gomock.Controller, m *MockIOperatorCollection)
+		want          error
+		wantErr       bool
 	}{
 		{
 			name: "check resource counts successfully",
 			args: args{
-				ctx:  context.Background(),
-				mock: mock,
+				ctx: context.Background(),
+			},
+			prepareMockFn: func(c *gomock.Controller, m *MockIOperatorCollection) {
+				var operators []IOperator
+
+				cloudformationStackOperatorMock := NewMockIOperator(c)
+				s3BucketOperatorMock := NewMockIOperator(c)
+				iamRoleOperatorMock := NewMockIOperator(c)
+				ecrRepositoryOperatorMock := NewMockIOperator(c)
+				backupVaultOperatorMock := NewMockIOperator(c)
+				customOperatorMock := NewMockIOperator(c)
+
+				cloudformationStackOperatorMock.EXPECT().GetResourcesLength().Return(1)
+				s3BucketOperatorMock.EXPECT().GetResourcesLength().Return(1)
+				iamRoleOperatorMock.EXPECT().GetResourcesLength().Return(1)
+				ecrRepositoryOperatorMock.EXPECT().GetResourcesLength().Return(1)
+				backupVaultOperatorMock.EXPECT().GetResourcesLength().Return(1)
+				customOperatorMock.EXPECT().GetResourcesLength().Return(1)
+
+				operators = append(operators, cloudformationStackOperatorMock)
+				operators = append(operators, s3BucketOperatorMock)
+				operators = append(operators, iamRoleOperatorMock)
+				operators = append(operators, ecrRepositoryOperatorMock)
+				operators = append(operators, backupVaultOperatorMock)
+				operators = append(operators, customOperatorMock)
+
+				m.EXPECT().GetOperators().Return(operators)
+
+				m.EXPECT().GetLogicalResourceIds().Return(
+					[]string{
+						"logicalResourceId1",
+						"logicalResourceId2",
+						"logicalResourceId3",
+						"logicalResourceId4",
+						"logicalResourceId5",
+						"logicalResourceId6",
+					},
+				)
 			},
 			want:    nil,
 			wantErr: false,
@@ -79,8 +140,42 @@ func TestOperatorManager_CheckResourceCounts(t *testing.T) {
 		{
 			name: "check resource counts failure",
 			args: args{
-				ctx:  context.Background(),
-				mock: incorrectResourceCountsMock,
+				ctx: context.Background(),
+			},
+			prepareMockFn: func(c *gomock.Controller, m *MockIOperatorCollection) {
+				var operators []IOperator
+
+				cloudformationStackOperatorMock := NewMockIOperator(c)
+				s3BucketOperatorMock := NewMockIOperator(c)
+				iamRoleOperatorMock := NewMockIOperator(c)
+				ecrRepositoryOperatorMock := NewMockIOperator(c)
+				backupVaultOperatorMock := NewMockIOperator(c)
+				customOperatorMock := NewMockIOperator(c)
+
+				cloudformationStackOperatorMock.EXPECT().GetResourcesLength().Return(1)
+				s3BucketOperatorMock.EXPECT().GetResourcesLength().Return(1)
+				iamRoleOperatorMock.EXPECT().GetResourcesLength().Return(1)
+				ecrRepositoryOperatorMock.EXPECT().GetResourcesLength().Return(1)
+				backupVaultOperatorMock.EXPECT().GetResourcesLength().Return(1)
+				customOperatorMock.EXPECT().GetResourcesLength().Return(1)
+
+				operators = append(operators, cloudformationStackOperatorMock)
+				operators = append(operators, s3BucketOperatorMock)
+				operators = append(operators, iamRoleOperatorMock)
+				operators = append(operators, ecrRepositoryOperatorMock)
+				operators = append(operators, backupVaultOperatorMock)
+				operators = append(operators, customOperatorMock)
+
+				m.EXPECT().GetOperators().Return(operators)
+
+				m.EXPECT().GetLogicalResourceIds().Return(
+					[]string{
+						"logicalResourceId1",
+						"logicalResourceId2",
+					},
+				)
+
+				m.EXPECT().RaiseUnsupportedResourceError().Return(fmt.Errorf("UnsupportedResourceError"))
 			},
 			want:    fmt.Errorf("UnsupportedResourceError"),
 			wantErr: true,
@@ -89,7 +184,11 @@ func TestOperatorManager_CheckResourceCounts(t *testing.T) {
 
 	for _, tt := range cases {
 		t.Run(tt.name, func(t *testing.T) {
-			operatorManager := NewOperatorManager(tt.args.mock)
+			ctrl := gomock.NewController(t)
+			collectionMock := NewMockIOperatorCollection(ctrl)
+			tt.prepareMockFn(ctrl, collectionMock)
+
+			operatorManager := NewOperatorManager(collectionMock)
 
 			err := operatorManager.CheckResourceCounts()
 			if (err != nil) != tt.wantErr {
@@ -107,25 +206,47 @@ func TestOperatorManager_CheckResourceCounts(t *testing.T) {
 func TestOperatorManager_DeleteResourceCollection(t *testing.T) {
 	io.NewLogger(false)
 
-	mock := NewMockOperatorCollection()
-	operatorDeleteResourcesMock := NewOperatorDeleteResourcesMockOperatorCollection()
-
 	type args struct {
-		ctx  context.Context
-		mock IOperatorCollection
+		ctx context.Context
 	}
 
 	cases := []struct {
-		name    string
-		args    args
-		want    error
-		wantErr bool
+		name          string
+		args          args
+		prepareMockFn func(c *gomock.Controller, m *MockIOperatorCollection)
+		want          error
+		wantErr       bool
 	}{
 		{
 			name: "delete resource collection successfully",
 			args: args{
-				ctx:  context.Background(),
-				mock: mock,
+				ctx: context.Background(),
+			},
+			prepareMockFn: func(c *gomock.Controller, m *MockIOperatorCollection) {
+				var operators []IOperator
+
+				cloudformationStackOperatorMock := NewMockIOperator(c)
+				s3BucketOperatorMock := NewMockIOperator(c)
+				iamRoleOperatorMock := NewMockIOperator(c)
+				ecrRepositoryOperatorMock := NewMockIOperator(c)
+				backupVaultOperatorMock := NewMockIOperator(c)
+				customOperatorMock := NewMockIOperator(c)
+
+				cloudformationStackOperatorMock.EXPECT().DeleteResources(gomock.Any()).Return(nil)
+				s3BucketOperatorMock.EXPECT().DeleteResources(gomock.Any()).Return(nil)
+				iamRoleOperatorMock.EXPECT().DeleteResources(gomock.Any()).Return(nil)
+				ecrRepositoryOperatorMock.EXPECT().DeleteResources(gomock.Any()).Return(nil)
+				backupVaultOperatorMock.EXPECT().DeleteResources(gomock.Any()).Return(nil)
+				customOperatorMock.EXPECT().DeleteResources(gomock.Any()).Return(nil)
+
+				operators = append(operators, cloudformationStackOperatorMock)
+				operators = append(operators, s3BucketOperatorMock)
+				operators = append(operators, iamRoleOperatorMock)
+				operators = append(operators, ecrRepositoryOperatorMock)
+				operators = append(operators, backupVaultOperatorMock)
+				operators = append(operators, customOperatorMock)
+
+				m.EXPECT().GetOperators().Return(operators)
 			},
 			want:    nil,
 			wantErr: false,
@@ -133,8 +254,33 @@ func TestOperatorManager_DeleteResourceCollection(t *testing.T) {
 		{
 			name: "delete resource collection failure",
 			args: args{
-				ctx:  context.Background(),
-				mock: operatorDeleteResourcesMock,
+				ctx: context.Background(),
+			},
+			prepareMockFn: func(c *gomock.Controller, m *MockIOperatorCollection) {
+				var operators []IOperator
+
+				cloudformationStackOperatorMock := NewMockIOperator(c)
+				s3BucketOperatorMock := NewMockIOperator(c)
+				iamRoleOperatorMock := NewMockIOperator(c)
+				ecrRepositoryOperatorMock := NewMockIOperator(c)
+				backupVaultOperatorMock := NewMockIOperator(c)
+				customOperatorMock := NewMockIOperator(c)
+
+				cloudformationStackOperatorMock.EXPECT().DeleteResources(gomock.Any()).Return(fmt.Errorf("ErrorDeleteResources"))
+				s3BucketOperatorMock.EXPECT().DeleteResources(gomock.Any()).Return(nil)
+				iamRoleOperatorMock.EXPECT().DeleteResources(gomock.Any()).Return(nil)
+				ecrRepositoryOperatorMock.EXPECT().DeleteResources(gomock.Any()).Return(nil)
+				backupVaultOperatorMock.EXPECT().DeleteResources(gomock.Any()).Return(nil)
+				customOperatorMock.EXPECT().DeleteResources(gomock.Any()).Return(nil)
+
+				operators = append(operators, cloudformationStackOperatorMock)
+				operators = append(operators, s3BucketOperatorMock)
+				operators = append(operators, iamRoleOperatorMock)
+				operators = append(operators, ecrRepositoryOperatorMock)
+				operators = append(operators, backupVaultOperatorMock)
+				operators = append(operators, customOperatorMock)
+
+				m.EXPECT().GetOperators().Return(operators)
 			},
 			want:    fmt.Errorf("ErrorDeleteResources"),
 			wantErr: true,
@@ -143,7 +289,11 @@ func TestOperatorManager_DeleteResourceCollection(t *testing.T) {
 
 	for _, tt := range cases {
 		t.Run(tt.name, func(t *testing.T) {
-			operatorManager := NewOperatorManager(tt.args.mock)
+			ctrl := gomock.NewController(t)
+			collectionMock := NewMockIOperatorCollection(ctrl)
+			tt.prepareMockFn(ctrl, collectionMock)
+
+			operatorManager := NewOperatorManager(collectionMock)
 
 			err := operatorManager.DeleteResourceCollection(tt.args.ctx)
 			if (err != nil) != tt.wantErr {
diff --git a/internal/operation/s3_bucket_test.go b/internal/operation/s3_bucket_test.go
index c1206de..01b87ba 100644
--- a/internal/operation/s3_bucket_test.go
+++ b/internal/operation/s3_bucket_test.go
@@ -7,8 +7,10 @@ import (
 
 	"github.com/aws/aws-sdk-go-v2/aws"
 	cfnTypes "github.com/aws/aws-sdk-go-v2/service/cloudformation/types"
+	"github.com/aws/aws-sdk-go-v2/service/s3/types"
 	"github.com/go-to-k/delstack/internal/io"
 	"github.com/go-to-k/delstack/pkg/client"
+	gomock "github.com/golang/mock/gomock"
 )
 
 /*
@@ -17,55 +19,52 @@ import (
 
 func TestS3BucketOperator_DeleteS3Bucket(t *testing.T) {
 	io.NewLogger(false)
-	mock := client.NewMockS3()
-	allErrorMock := client.NewAllErrorMockS3()
-	deleteBucketErrorMock := client.NewDeleteBucketErrorMockS3()
-	deleteObjectsErrorMock := client.NewDeleteObjectsErrorMockS3()
-	deleteObjectsErrorAfterZeroLengthMock := client.NewDeleteObjectsErrorAfterZeroLengthMockS3()
-	deleteObjectsOutputErrorMock := client.NewDeleteObjectsOutputErrorMockS3()
-	deleteObjectsOutputErrorAfterZeroLengthMock := client.NewDeleteObjectsOutputErrorAfterZeroLengthMockS3()
-	listObjectVersionsErrorMock := client.NewListObjectVersionsErrorMockS3()
-	checkBucketExistsErrorMock := client.NewCheckBucketExistsErrorMockS3()
-	checkBucketNotExistsMock := client.NewCheckBucketNotExistsMockS3()
 
 	type args struct {
 		ctx        context.Context
 		bucketName *string
-		client     client.IS3
 	}
 
 	cases := []struct {
-		name    string
-		args    args
-		want    error
-		wantErr bool
+		name          string
+		args          args
+		prepareMockFn func(m *client.MockIS3)
+		want          error
+		wantErr       bool
 	}{
 		{
 			name: "delete bucket successfully",
 			args: args{
 				ctx:        context.Background(),
 				bucketName: aws.String("test"),
-				client:     mock,
+			},
+			prepareMockFn: func(m *client.MockIS3) {
+				m.EXPECT().CheckBucketExists(gomock.Any(), aws.String("test")).Return(true, nil)
+				m.EXPECT().ListObjectVersions(gomock.Any(), aws.String("test")).Return(
+					[]types.ObjectIdentifier{
+						{
+							Key:       aws.String("KeyForVersions"),
+							VersionId: aws.String("VersionIdForVersions"),
+						},
+						{
+							Key:       aws.String("KeyForDeleteMarkers"),
+							VersionId: aws.String("VersionIdForDeleteMarkers"),
+						},
+					}, nil)
+				m.EXPECT().DeleteObjects(gomock.Any(), aws.String("test"), gomock.Any()).Return([]types.Error{}, nil)
+				m.EXPECT().DeleteBucket(gomock.Any(), aws.String("test")).Return(nil)
 			},
 			want:    nil,
 			wantErr: false,
 		},
-		{
-			name: "delete bucket failure for all errors",
-			args: args{
-				ctx:        context.Background(),
-				bucketName: aws.String("test"),
-				client:     allErrorMock,
-			},
-			want:    fmt.Errorf("ListBucketsError"),
-			wantErr: true,
-		},
 		{
 			name: "delete bucket failure for check bucket exists errors",
 			args: args{
 				ctx:        context.Background(),
 				bucketName: aws.String("test"),
-				client:     checkBucketExistsErrorMock,
+			},
+			prepareMockFn: func(m *client.MockIS3) {
+				m.EXPECT().CheckBucketExists(gomock.Any(), aws.String("test")).Return(false, fmt.Errorf("ListBucketsError"))
 			},
 			want:    fmt.Errorf("ListBucketsError"),
 			wantErr: true,
@@ -75,7 +74,9 @@ func TestS3BucketOperator_DeleteS3Bucket(t *testing.T) {
 			args: args{
 				ctx:        context.Background(),
 				bucketName: aws.String("test"),
-				client:     checkBucketNotExistsMock,
+			},
+			prepareMockFn: func(m *client.MockIS3) {
+				m.EXPECT().CheckBucketExists(gomock.Any(), aws.String("test")).Return(false, nil)
 			},
 			want:    nil,
 			wantErr: false,
@@ -85,7 +86,10 @@ func TestS3BucketOperator_DeleteS3Bucket(t *testing.T) {
 			args: args{
 				ctx:        context.Background(),
 				bucketName: aws.String("test"),
-				client:     listObjectVersionsErrorMock,
+			},
+			prepareMockFn: func(m *client.MockIS3) {
+				m.EXPECT().CheckBucketExists(gomock.Any(), aws.String("test")).Return(true, nil)
+				m.EXPECT().ListObjectVersions(gomock.Any(), aws.String("test")).Return(nil, fmt.Errorf("ListObjectVersionsError"))
 			},
 			want:    fmt.Errorf("ListObjectVersionsError"),
 			wantErr: true,
@@ -95,17 +99,35 @@ func TestS3BucketOperator_DeleteS3Bucket(t *testing.T) {
 			args: args{
 				ctx:        context.Background(),
 				bucketName: aws.String("test"),
-				client:     deleteObjectsErrorMock,
+			},
+			prepareMockFn: func(m *client.MockIS3) {
+				m.EXPECT().CheckBucketExists(gomock.Any(), aws.String("test")).Return(true, nil)
+				m.EXPECT().ListObjectVersions(gomock.Any(), aws.String("test")).Return(
+					[]types.ObjectIdentifier{
+						{
+							Key:       aws.String("KeyForVersions"),
+							VersionId: aws.String("VersionIdForVersions"),
+						},
+						{
+							Key:       aws.String("KeyForDeleteMarkers"),
+							VersionId: aws.String("VersionIdForDeleteMarkers"),
+						},
+					}, nil)
+				m.EXPECT().DeleteObjects(gomock.Any(), aws.String("test"), gomock.Any()).Return([]types.Error{}, fmt.Errorf("DeleteObjectsError"))
 			},
 			want:    fmt.Errorf("DeleteObjectsError"),
 			wantErr: true,
 		},
 		{
-			name: "delete bucket successfully for delete objects errors after zero length",
+			name: "delete bucket successfully for ListObjectVersions with zero length",
 			args: args{
 				ctx:        context.Background(),
 				bucketName: aws.String("test"),
-				client:     deleteObjectsErrorAfterZeroLengthMock,
+			},
+			prepareMockFn: func(m *client.MockIS3) {
+				m.EXPECT().CheckBucketExists(gomock.Any(), aws.String("test")).Return(true, nil)
+				m.EXPECT().ListObjectVersions(gomock.Any(), aws.String("test")).Return([]types.ObjectIdentifier{}, nil)
+				m.EXPECT().DeleteBucket(gomock.Any(), aws.String("test")).Return(nil)
 			},
 			want:    nil,
 			wantErr: false,
@@ -115,27 +137,53 @@ func TestS3BucketOperator_DeleteS3Bucket(t *testing.T) {
 			args: args{
 				ctx:        context.Background(),
 				bucketName: aws.String("test"),
-				client:     deleteObjectsOutputErrorMock,
+			},
+			prepareMockFn: func(m *client.MockIS3) {
+				m.EXPECT().CheckBucketExists(gomock.Any(), aws.String("test")).Return(true, nil)
+				m.EXPECT().ListObjectVersions(gomock.Any(), aws.String("test")).Return(
+					[]types.ObjectIdentifier{
+						{
+							Key:       aws.String("KeyForVersions"),
+							VersionId: aws.String("VersionIdForVersions"),
+						},
+						{
+							Key:       aws.String("KeyForDeleteMarkers"),
+							VersionId: aws.String("VersionIdForDeleteMarkers"),
+						},
+					}, nil)
+				m.EXPECT().DeleteObjects(gomock.Any(), aws.String("test"), gomock.Any()).Return([]types.Error{
+					{
+						Key:       aws.String("Key"),
+						Code:      aws.String("Code"),
+						Message:   aws.String("Message"),
+						VersionId: aws.String("VersionId"),
+					},
+				}, nil)
 			},
 			want:    fmt.Errorf("DeleteObjectsError: followings \nCode: Code\nKey: Key\nVersionId: VersionId\nMessage: Message\n"),
 			wantErr: true,
 		},
-		{
-			name: "delete bucket successfully for delete objects output errors after zero length",
-			args: args{
-				ctx:        context.Background(),
-				bucketName: aws.String("test"),
-				client:     deleteObjectsOutputErrorAfterZeroLengthMock,
-			},
-			want:    nil,
-			wantErr: false,
-		},
 		{
 			name: "delete bucket failure for delete bucket errors",
 			args: args{
 				ctx:        context.Background(),
 				bucketName: aws.String("test"),
-				client:     deleteBucketErrorMock,
+			},
+			prepareMockFn: func(m *client.MockIS3) {
+				m.EXPECT().CheckBucketExists(gomock.Any(), aws.String("test")).Return(true, nil)
+				m.EXPECT().ListObjectVersions(gomock.Any(), aws.String("test")).Return(
+					[]types.ObjectIdentifier{
+						{
+							Key:       aws.String("KeyForVersions"),
+							VersionId: aws.String("VersionIdForVersions"),
+						},
+						{
+							Key:       aws.String("KeyForDeleteMarkers"),
+							VersionId: aws.String("VersionIdForDeleteMarkers"),
+						},
+					}, nil)
+				m.EXPECT().DeleteObjects(gomock.Any(), aws.String("test"), gomock.Any()).Return([]types.Error{}, nil)
+				m.EXPECT().DeleteBucket(gomock.Any(), aws.String("test")).Return(fmt.Errorf("DeleteBucketError"))
 			},
 			want:    fmt.Errorf("DeleteBucketError"),
 			wantErr: true,
@@ -144,7 +192,11 @@ func TestS3BucketOperator_DeleteS3Bucket(t *testing.T) {
 
 	for _, tt := range cases {
 		t.Run(tt.name, func(t *testing.T) {
-			s3BucketOperator := NewS3BucketOperator(tt.args.client)
+			ctrl := gomock.NewController(t)
+			s3Mock := client.NewMockIS3(ctrl)
+			tt.prepareMockFn(s3Mock)
+
+			s3BucketOperator := NewS3BucketOperator(s3Mock)
 
 			err := s3BucketOperator.DeleteS3Bucket(tt.args.ctx, tt.args.bucketName)
 			if (err != nil) != tt.wantErr {
@@ -161,25 +213,38 @@ func TestS3BucketOperator_DeleteS3Bucket(t *testing.T) {
 
 func TestS3BucketOperator_DeleteResourcesForS3Bucket(t *testing.T) {
 	io.NewLogger(false)
-	mock := client.NewMockS3()
-	allErrorMock := client.NewAllErrorMockS3()
 
 	type args struct {
-		ctx    context.Context
-		client client.IS3
+		ctx context.Context
 	}
 
 	cases := []struct {
-		name    string
-		args    args
-		want    error
-		wantErr bool
+		name          string
+		args          args
+		prepareMockFn func(m *client.MockIS3)
+		want          error
+		wantErr       bool
 	}{
 		{
 			name: "delete resources successfully",
 			args: args{
-				ctx:    context.Background(),
-				client: mock,
+				ctx: context.Background(),
+			},
+			prepareMockFn: func(m *client.MockIS3) {
+				m.EXPECT().CheckBucketExists(gomock.Any(), aws.String("PhysicalResourceId1")).Return(true, nil)
+				m.EXPECT().ListObjectVersions(gomock.Any(), aws.String("PhysicalResourceId1")).Return(
+					[]types.ObjectIdentifier{
+						{
+							Key:       aws.String("KeyForVersions"),
+							VersionId: aws.String("VersionIdForVersions"),
+						},
+						{
+							Key:       aws.String("KeyForDeleteMarkers"),
+							VersionId: aws.String("VersionIdForDeleteMarkers"),
+						},
+					}, nil)
+				m.EXPECT().DeleteObjects(gomock.Any(), aws.String("PhysicalResourceId1"), gomock.Any()).Return([]types.Error{}, nil)
+				m.EXPECT().DeleteBucket(gomock.Any(), aws.String("PhysicalResourceId1")).Return(nil)
 			},
 			want:    nil,
 			wantErr: false,
@@ -187,8 +252,10 @@ func TestS3BucketOperator_DeleteResourcesForS3Bucket(t *testing.T) {
 		{
 			name: "delete resources failure",
 			args: args{
-				ctx:    context.Background(),
-				client: allErrorMock,
+				ctx: context.Background(),
+			},
+			prepareMockFn: func(m *client.MockIS3) {
+				m.EXPECT().CheckBucketExists(gomock.Any(), aws.String("PhysicalResourceId1")).Return(false, fmt.Errorf("ListBucketsError"))
 			},
 			want:    fmt.Errorf("ListBucketsError"),
 			wantErr: true,
@@ -197,7 +264,12 @@ func TestS3BucketOperator_DeleteResourcesForS3Bucket(t *testing.T) {
 
 	for _, tt := range cases {
 		t.Run(tt.name, func(t *testing.T) {
-			s3BucketOperator := NewS3BucketOperator(tt.args.client)
+			ctrl := gomock.NewController(t)
+			s3Mock := client.NewMockIS3(ctrl)
+			tt.prepareMockFn(s3Mock)
+
+			s3BucketOperator := NewS3BucketOperator(s3Mock)
+
 			s3BucketOperator.AddResource(&cfnTypes.StackResourceSummary{
 				LogicalResourceId:  aws.String("LogicalResourceId1"),
 				ResourceStatus:     "DELETE_FAILED",