面试题答案
一键面试- 安装依赖:
- Go 1.18 及以上版本内置了
testing
包和mockgen
工具,用于生成 mock 代码。如果是旧版本,可以使用go get
安装github.com/golang/mock/gomock
和github.com/golang/mock/mockgen
。
- Go 1.18 及以上版本内置了
- 定义接口:
- 为了便于使用 mock,先定义一个接口,
FetchDataFromDB
函数将通过实现此接口来工作。
type DataFetcher interface { FetchDataFromDB() (string, error) }
- 为了便于使用 mock,先定义一个接口,
- 修改
ProcessData
函数:- 让
ProcessData
函数依赖这个接口,而不是直接调用FetchDataFromDB
函数。
func ProcessData(fetcher DataFetcher) (string, error) { data, err := fetcher.FetchDataFromDB() if err!= nil { return "", err } // 对 data 进行处理,这里简单返回 data return data, nil }
- 让
- 生成 mock 代码:
- 使用
mockgen
工具生成 mock 代码。假设上述代码在main.go
文件中,执行以下命令:
mockgen -destination mock_data_fetcher.go -package main main DataFetcher
- 这会在
mock_data_fetcher.go
文件中生成DataFetcher
接口的 mock 实现,代码大致如下:
// Code generated by MockGen. DO NOT EDIT. // Source: main.go package main import ( "context" mock "github.com/golang/mock/gomock" ) // MockDataFetcher is a mock of DataFetcher interface. type MockDataFetcher struct { ctrl *mock.Controller recorder *MockDataFetcherMockRecorder } // MockDataFetcherMockRecorder is the mock recorder for MockDataFetcher. type MockDataFetcherMockRecorder struct { mock *mock.Controller } // NewMockDataFetcher creates a new mock instance. func NewMockDataFetcher(ctrl *mock.Controller) *MockDataFetcher { mock := &MockDataFetcher{ctrl: ctrl} mock.recorder = &MockDataFetcherMockRecorder{mock} return mock } // EXPECT returns an object that allows the caller to indicate expected use. func (m *MockDataFetcher) EXPECT() *MockDataFetcherMockRecorder { return m.recorder } // FetchDataFromDB mocks base method. func (m *MockDataFetcher) FetchDataFromDB() (string, error) { ret := m.ctrl.Call(m, "FetchDataFromDB") ret0, _ := ret[0].(string) ret1, _ := ret[1].(error) return ret0, ret1 } // FetchDataFromDB indicates an expected call of FetchDataFromDB. func (mr *MockDataFetcherMockRecorder) FetchDataFromDB() *mock.Call { return mr.mock.Call("FetchDataFromDB") }
- 使用
- 编写测试代码:
- 使用生成的 mock 代码来测试
ProcessData
函数。
package main import ( "testing" "github.com/golang/mock/gomock" ) func TestProcessData(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() mockFetcher := NewMockDataFetcher(ctrl) expectedData := "test data" mockFetcher.EXPECT().FetchDataFromDB().Return(expectedData, nil) result, err := ProcessData(mockFetcher) if err!= nil { t.Errorf("ProcessData() error = %v", err) } if result!= expectedData { t.Errorf("ProcessData() result = %v, want %v", result, expectedData) } }
- 使用生成的 mock 代码来测试
以上步骤和代码示例展示了如何使用 Mock 技术在不连接真实数据库的情况下测试 ProcessData
函数。