希望所有开发人员都能写测试,这是一种极好的习惯。
虽然要写,但是写的有问题也是蛮头疼的。
一个web的可行测试,测试是需要在任何情况下都跑的,比如我们不能联网了,测试一定也是要跑的,所以就产生了mock。我们在写逻辑代码时候就需要考虑到这个问题。这里先原生展示一下,有很多支持完善的第三方库可自行学习,但是原理就是这么回事。
package mocktest import ( "encoding/json" "fmt" "net/http" ) type ValueGetter interface { GetValues() ([]float64, error) } type service struct { valueGetter ValueGetter } func (s service) averageForWeb() (float64, error) { values, err := s.valueGetter.GetValues() if err != nil { return 0, err } var total float64 = 0 for _, value := range values { total += value } return total / float64(len(values)), nil } // The real implementation type httpValueGetter struct { } func (h httpValueGetter) GetValues() ([]float64, error) { resp, err := http.DefaultClient.Get("http://our-api.com/numbers") if err != nil { return nil, err } values := []float64{} if err := json.NewDecoder(resp.Body).Decode(&values); err != nil { return nil, nil } return values, nil } type mockValueGetter struct { values []float64 err error } func (m mockValueGetter) GetValues() ([]float64, error) { return m.values, m.err } func main() { service := service{valueGetter:httpValueGetter{}} average, err := service.averageForWeb() if err != nil { panic(err) } fmt.Println(average) }
test
package mocktest import ( "fmt" "testing" ) func Test_Average(t *testing.T) { testError := fmt.Errorf("an example error to compare against") tests := []struct{ name string input []float64 err error expectedResult float64 expectedErr error } { { name:"three normal values", input:[]float64{3.5, 2.5, 9.0}, expectedResult:5, }, { name:"error case", input:[]float64{3.5, 2.5, 9.0}, err:testError, expectedErr:testError, }, } for _, test := range tests { service := service{valueGetter:mockValueGetter{ values:test.input, err:test.err, }} result, err := service.averageForWeb() if err != test.expectedErr { t.Errorf( "for average test %s, got err %v but expected %f", test.name, test.expectedResult, test.expectedErr, ) } if result != test.expectedResult { //... // 应该在这里设置expecteErr t.Errorf( "for average test %s, got result %f but expected %f", test.name, result, test.expectedResult, ) } } }
简单来讲,就是一种解耦分离的策略。不要把问题想复杂,更不要被各种人有意无意的欺骗,把观点付诸于行动最重要。
end