// Code generated by MockGen. DO NOT EDIT.
// Source: git.fd.io/govpp.git/api (Interfaces: Channel)

// Package mock_api is a generated GoMock package.
package main

import (
	reflect "reflect"
	time "time"

	api "git.fd.io/govpp.git/api"
	gomock "github.com/golang/mock/gomock"
)

// MockChannel is a mock of Channel interface
type MockChannel struct {
	ctrl     *gomock.Controller
	recorder *MockChannelMockRecorder
}

// MockChannelMockRecorder is the mock recorder for MockChannel
type MockChannelMockRecorder struct {
	mock *MockChannel
}

// NewMockChannel creates a new mock instance
func NewMockChannel(ctrl *gomock.Controller) *MockChannel {
	mock := &MockChannel{ctrl: ctrl}
	mock.recorder = &MockChannelMockRecorder{mock}
	return mock
}

// EXPECT returns an object that allows the caller to indicate expected use
func (m *MockChannel) EXPECT() *MockChannelMockRecorder {
	return m.recorder
}

// Close mocks base method
func (m *MockChannel) Close() {
	m.ctrl.Call(m, "Close")
}

// Close indicates an expected call of Close
func (mr *MockChannelMockRecorder) Close() *gomock.Call {
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockChannel)(nil).Close))
}

// SendMultiRequest mocks base method
func (m *MockChannel) SendMultiRequest(arg0 api.Message) api.MultiRequestCtx {
	ret := m.ctrl.Call(m, "SendMultiRequest", arg0)
	ret0, _ := ret[0].(api.MultiRequestCtx)
	return ret0
}

// SendMultiRequest indicates an expected call of SendMultiRequest
func (mr *MockChannelMockRecorder) SendMultiRequest(arg0 interface{}) *gomock.Call {
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendMultiRequest", reflect.TypeOf((*MockChannel)(nil).SendMultiRequest), arg0)
}

// SendRequest mocks base method
func (m *MockChannel) SendRequest(arg0 api.Message) api.RequestCtx {
	ret := m.ctrl.Call(m, "SendRequest", arg0)
	ret0, _ := ret[0].(api.RequestCtx)
	return ret0
}

// SendRequest indicates an expected call of SendRequest
func (mr *MockChannelMockRecorder) SendRequest(arg0 interface{}) *gomock.Call {
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendRequest", reflect.TypeOf((*MockChannel)(nil).SendRequest), arg0)
}

// SetReplyTimeout mocks base method
func (m *MockChannel) SetReplyTimeout(arg0 time.Duration) {
	m.ctrl.Call(m, "SetReplyTimeout", arg0)
}

// SetReplyTimeout indicates an expected call of SetReplyTimeout
func (mr *MockChannelMockRecorder) SetReplyTimeout(arg0 interface{}) *gomock.Call {
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetReplyTimeout", reflect.TypeOf((*MockChannel)(nil).SetReplyTimeout), arg0)
}

// SubscribeNotification mocks base method
func (m *MockChannel) SubscribeNotification(arg0 chan api.Message, arg1 api.Message) (api.SubscriptionCtx, error) {
	ret := m.ctrl.Call(m, "SubscribeNotification", arg0, arg1)
	ret0, _ := ret[0].(api.SubscriptionCtx)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// SubscribeNotification indicates an expected call of SubscribeNotification
func (mr *MockChannelMockRecorder) SubscribeNotification(arg0, arg1 interface{}) *gomock.Call {
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubscribeNotification", reflect.TypeOf((*MockChannel)(nil).SubscribeNotification), arg0, arg1)
}
