/*
 * 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 cache

import (
	plc4go "github.com/apache/plc4x/plc4go/pkg/api"
	mock "github.com/stretchr/testify/mock"
)

// MockPlcConnectionCache is an autogenerated mock type for the PlcConnectionCache type
type MockPlcConnectionCache struct {
	mock.Mock
}

type MockPlcConnectionCache_Expecter struct {
	mock *mock.Mock
}

func (_m *MockPlcConnectionCache) EXPECT() *MockPlcConnectionCache_Expecter {
	return &MockPlcConnectionCache_Expecter{mock: &_m.Mock}
}

// Close provides a mock function with given fields:
func (_m *MockPlcConnectionCache) Close() <-chan PlcConnectionCacheCloseResult {
	ret := _m.Called()

	var r0 <-chan PlcConnectionCacheCloseResult
	if rf, ok := ret.Get(0).(func() <-chan PlcConnectionCacheCloseResult); ok {
		r0 = rf()
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(<-chan PlcConnectionCacheCloseResult)
		}
	}

	return r0
}

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

// Close is a helper method to define mock.On call
func (_e *MockPlcConnectionCache_Expecter) Close() *MockPlcConnectionCache_Close_Call {
	return &MockPlcConnectionCache_Close_Call{Call: _e.mock.On("Close")}
}

func (_c *MockPlcConnectionCache_Close_Call) Run(run func()) *MockPlcConnectionCache_Close_Call {
	_c.Call.Run(func(args mock.Arguments) {
		run()
	})
	return _c
}

func (_c *MockPlcConnectionCache_Close_Call) Return(_a0 <-chan PlcConnectionCacheCloseResult) *MockPlcConnectionCache_Close_Call {
	_c.Call.Return(_a0)
	return _c
}

func (_c *MockPlcConnectionCache_Close_Call) RunAndReturn(run func() <-chan PlcConnectionCacheCloseResult) *MockPlcConnectionCache_Close_Call {
	_c.Call.Return(run)
	return _c
}

// GetConnection provides a mock function with given fields: connectionString
func (_m *MockPlcConnectionCache) GetConnection(connectionString string) <-chan plc4go.PlcConnectionConnectResult {
	ret := _m.Called(connectionString)

	var r0 <-chan plc4go.PlcConnectionConnectResult
	if rf, ok := ret.Get(0).(func(string) <-chan plc4go.PlcConnectionConnectResult); ok {
		r0 = rf(connectionString)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(<-chan plc4go.PlcConnectionConnectResult)
		}
	}

	return r0
}

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

// GetConnection is a helper method to define mock.On call
//   - connectionString string
func (_e *MockPlcConnectionCache_Expecter) GetConnection(connectionString interface{}) *MockPlcConnectionCache_GetConnection_Call {
	return &MockPlcConnectionCache_GetConnection_Call{Call: _e.mock.On("GetConnection", connectionString)}
}

func (_c *MockPlcConnectionCache_GetConnection_Call) Run(run func(connectionString string)) *MockPlcConnectionCache_GetConnection_Call {
	_c.Call.Run(func(args mock.Arguments) {
		run(args[0].(string))
	})
	return _c
}

func (_c *MockPlcConnectionCache_GetConnection_Call) Return(_a0 <-chan plc4go.PlcConnectionConnectResult) *MockPlcConnectionCache_GetConnection_Call {
	_c.Call.Return(_a0)
	return _c
}

func (_c *MockPlcConnectionCache_GetConnection_Call) RunAndReturn(run func(string) <-chan plc4go.PlcConnectionConnectResult) *MockPlcConnectionCache_GetConnection_Call {
	_c.Call.Return(run)
	return _c
}

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

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

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

	return mock
}
