// Code generated by MockGen. DO NOT EDIT.
// Source: monorail.pb.go

// Package monorail is a generated GoMock package.
package monorail

import (
	reflect "reflect"

	context "context"

	gomock "github.com/golang/mock/gomock"
	grpc "google.golang.org/grpc"
)

// MockMonorailClient is a mock of MonorailClient interface
type MockMonorailClient struct {
	ctrl     *gomock.Controller
	recorder *MockMonorailClientMockRecorder
}

// MockMonorailClientMockRecorder is the mock recorder for MockMonorailClient
type MockMonorailClientMockRecorder struct {
	mock *MockMonorailClient
}

// NewMockMonorailClient creates a new mock instance
func NewMockMonorailClient(ctrl *gomock.Controller) *MockMonorailClient {
	mock := &MockMonorailClient{ctrl: ctrl}
	mock.recorder = &MockMonorailClientMockRecorder{mock}
	return mock
}

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

// InsertIssue mocks base method
func (m *MockMonorailClient) InsertIssue(ctx context.Context, in *InsertIssueRequest, opts ...grpc.CallOption) (*InsertIssueResponse, error) {
	varargs := []interface{}{ctx, in}
	for _, a := range opts {
		varargs = append(varargs, a)
	}
	ret := m.ctrl.Call(m, "InsertIssue", varargs...)
	ret0, _ := ret[0].(*InsertIssueResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// InsertIssue indicates an expected call of InsertIssue
func (mr *MockMonorailClientMockRecorder) InsertIssue(ctx, in interface{}, opts ...interface{}) *gomock.Call {
	varargs := append([]interface{}{ctx, in}, opts...)
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InsertIssue", reflect.TypeOf((*MockMonorailClient)(nil).InsertIssue), varargs...)
}

// InsertComment mocks base method
func (m *MockMonorailClient) InsertComment(ctx context.Context, in *InsertCommentRequest, opts ...grpc.CallOption) (*InsertCommentResponse, error) {
	varargs := []interface{}{ctx, in}
	for _, a := range opts {
		varargs = append(varargs, a)
	}
	ret := m.ctrl.Call(m, "InsertComment", varargs...)
	ret0, _ := ret[0].(*InsertCommentResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// InsertComment indicates an expected call of InsertComment
func (mr *MockMonorailClientMockRecorder) InsertComment(ctx, in interface{}, opts ...interface{}) *gomock.Call {
	varargs := append([]interface{}{ctx, in}, opts...)
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InsertComment", reflect.TypeOf((*MockMonorailClient)(nil).InsertComment), varargs...)
}

// IssuesList mocks base method
func (m *MockMonorailClient) IssuesList(ctx context.Context, in *IssuesListRequest, opts ...grpc.CallOption) (*IssuesListResponse, error) {
	varargs := []interface{}{ctx, in}
	for _, a := range opts {
		varargs = append(varargs, a)
	}
	ret := m.ctrl.Call(m, "IssuesList", varargs...)
	ret0, _ := ret[0].(*IssuesListResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// IssuesList indicates an expected call of IssuesList
func (mr *MockMonorailClientMockRecorder) IssuesList(ctx, in interface{}, opts ...interface{}) *gomock.Call {
	varargs := append([]interface{}{ctx, in}, opts...)
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IssuesList", reflect.TypeOf((*MockMonorailClient)(nil).IssuesList), varargs...)
}

// MockMonorailServer is a mock of MonorailServer interface
type MockMonorailServer struct {
	ctrl     *gomock.Controller
	recorder *MockMonorailServerMockRecorder
}

// MockMonorailServerMockRecorder is the mock recorder for MockMonorailServer
type MockMonorailServerMockRecorder struct {
	mock *MockMonorailServer
}

// NewMockMonorailServer creates a new mock instance
func NewMockMonorailServer(ctrl *gomock.Controller) *MockMonorailServer {
	mock := &MockMonorailServer{ctrl: ctrl}
	mock.recorder = &MockMonorailServerMockRecorder{mock}
	return mock
}

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

// InsertIssue mocks base method
func (m *MockMonorailServer) InsertIssue(arg0 context.Context, arg1 *InsertIssueRequest) (*InsertIssueResponse, error) {
	ret := m.ctrl.Call(m, "InsertIssue", arg0, arg1)
	ret0, _ := ret[0].(*InsertIssueResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

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

// InsertComment mocks base method
func (m *MockMonorailServer) InsertComment(arg0 context.Context, arg1 *InsertCommentRequest) (*InsertCommentResponse, error) {
	ret := m.ctrl.Call(m, "InsertComment", arg0, arg1)
	ret0, _ := ret[0].(*InsertCommentResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

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

// IssuesList mocks base method
func (m *MockMonorailServer) IssuesList(arg0 context.Context, arg1 *IssuesListRequest) (*IssuesListResponse, error) {
	ret := m.ctrl.Call(m, "IssuesList", arg0, arg1)
	ret0, _ := ret[0].(*IssuesListResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

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