/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

// Code generated by mockery v2.28.2. DO NOT EDIT.

package spi

import mock "github.com/stretchr/testify/mock"

// MockHandleError is an autogenerated mock type for the HandleError type
type MockHandleError struct {
	mock.Mock
}

type MockHandleError_Expecter struct {
	mock *mock.Mock
}

func (_m *MockHandleError) EXPECT() *MockHandleError_Expecter {
	return &MockHandleError_Expecter{mock: &_m.Mock}
}

// Execute provides a mock function with given fields: err
func (_m *MockHandleError) Execute(err error) error {
	ret := _m.Called(err)

	var r0 error
	if rf, ok := ret.Get(0).(func(error) error); ok {
		r0 = rf(err)
	} else {
		r0 = ret.Error(0)
	}

	return r0
}

// MockHandleError_Execute_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Execute'
type MockHandleError_Execute_Call struct {
	*mock.Call
}

// Execute is a helper method to define mock.On call
//   - err error
func (_e *MockHandleError_Expecter) Execute(err interface{}) *MockHandleError_Execute_Call {
	return &MockHandleError_Execute_Call{Call: _e.mock.On("Execute", err)}
}

func (_c *MockHandleError_Execute_Call) Run(run func(err error)) *MockHandleError_Execute_Call {
	_c.Call.Run(func(args mock.Arguments) {
		run(args[0].(error))
	})
	return _c
}

func (_c *MockHandleError_Execute_Call) Return(_a0 error) *MockHandleError_Execute_Call {
	_c.Call.Return(_a0)
	return _c
}

func (_c *MockHandleError_Execute_Call) RunAndReturn(run func(error) error) *MockHandleError_Execute_Call {
	_c.Call.Return(run)
	return _c
}

type mockConstructorTestingTNewMockHandleError interface {
	mock.TestingT
	Cleanup(func())
}

// NewMockHandleError creates a new instance of MockHandleError. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
func NewMockHandleError(t mockConstructorTestingTNewMockHandleError) *MockHandleError {
	mock := &MockHandleError{}
	mock.Mock.Test(t)

	t.Cleanup(func() { mock.AssertExpectations(t) })

	return mock
}
