Go的可行测试

希望所有开发人员都能写测试,这是一种极好的习惯。

虽然要写,但是写的有问题也是蛮头疼的。

一个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

一个没有高级趣味的人。 email:hushui502@gmail.com
原文地址:https://www.cnblogs.com/CherryTab/p/12716394.html