最新公告
  • 欢迎您光临码农资源网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!加入我们
  • 如何在 golang 框架中编写依赖外部服务的单元测试?

    golang 框架中编写依赖于外部服务的单元测试可以使用以下技巧:模拟外部服务行为:定义并模拟服务接口。使用模拟类型来创建测试并断言外部服务行为。实战案例:使用模拟类型测试依赖于 http 服务的外部服务。模拟服务端行为,并更新客户端指向模拟服务端。执行测试并断言结果。

    如何在 golang 框架中编写依赖外部服务的单元测试?

    如何在 GoLang 框架中编写依赖外部服务的单元测试

    简介

    编写依赖于外部服务的单元测试可能是一项艰巨的任务。在本指南中,我们将介绍在 GoLang 框架中编写此类测试的技巧。

    立即学习go语言免费学习笔记(深入)”;

    模拟外部服务

    一种常见的技术是模拟外部服务行为。我们使用 [mock](https://github.com/golang/mock) 包来定义接口和模拟类型。

    package service
    
    // MyService 接口定义了外部服务行为
    type MyService interface {
        GetData() (string, error)
    }
    
    // MyServiceMock 是 MyService 接口的模拟类型
    type MyServiceMock struct {
        mock.Mock
    }
    
    // GetData 模拟外部服务的 GetData 方法
    func (m *MyServiceMock) GetData() (string, error) {
        ret := m.Called()
        return ret.Get(0).(string), ret.Error(1)
    }

    使用模拟类型

    我们可以使用模拟类型来创建单元测试并断言外部服务的行为。

    package service
    
    import (
        "testing"
        "time"
    )
    
    func TestService_GetData(t *testing.T) {
        // 创建模拟服务
        mockService := &MyServiceMock{}
    
        // 设置 mock 行为
        mockService.On("GetData").Return("sample data", nil).Once()
    
        service := NewService(mockService, time.Duration(0))
        data, err := service.GetData()
    
        // 断言
        if err != nil {
            t.Fatal(err)
        }
        if data != "sample data" {
            t.Fatalf("Expected 'sample data', got '%s'", data)
        }
    
        // 验证调用是否发生
        if !mockService.AssertCalled(t, "GetData") {
            t.Error("GetData() was not called")
        }
    }

    实战案例

    以下是如何在集成测试中使用模拟类型测试依赖于外部服务的 HTTP 服务的示例:

    package service_test
    
    import (
        "context"
        "fmt"
        "io"
        "net/http"
        "net/http/httptest"
        "strings"
        "testing"
    
        "github.com/stretchr/testify/assert"
    )
    
    func TestService_GetData(t *testing.T) {
        type args struct {
            ctx context.Context
            r   *http.Request
        }
        tests := []struct {
            name           string
            args           args
            mockStatusCode int
            expectedBody   string
        }{
            {
                "Success",
                args{context.Background(), new(http.Request)},
                http.StatusOK,
                "sample data",
            },
        }
    
        for _, tt := range tests {
            t.Run(tt.name, func(t *testing.T) {
                // 模拟服务端行为
                server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
                    if r.Method != "GET" {
                        t.Errorf("Unexpected HTTP method: %s", r.Method)
                    }
    
                    w.WriteHeader(tt.mockStatusCode)
                    _, _ = io.WriteString(w, tt.expectedBody)
                }))
                defer server.Close()
    
                // 更新请求以指向模拟服务端
                baseClient := Service.GetClient()
                t.Cleanup(func() { Service.SetClient(baseClient) })
                Service.SetClient(http.Client{Transport: &http.Transport{
                    Base:    &http.Transport{DisableCompression: true},
                    DialTLS: func(network, addr string) (net.Conn, error) {
                        return net.Dial(network, strings.Replace(addr, "localhost", server.Listener.Addr().String(), 1))
                    },
                }})
    
                // 执行测试
                result, err := Service.GetData(tt.args.ctx, tt.args.r)
                assert.Nil(t, err)
                assert.Equal(t, tt.expectedBody, result)
            })
        }
    }
    想要了解更多内容,请持续关注码农资源网,一起探索发现编程世界的无限可能!
    本站部分资源来源于网络,仅限用于学习和研究目的,请勿用于其他用途。
    如有侵权请发送邮件至1943759704@qq.com删除

    码农资源网 » 如何在 golang 框架中编写依赖外部服务的单元测试?
    • 7会员总数(位)
    • 25846资源总数(个)
    • 0本周发布(个)
    • 0 今日发布(个)
    • 294稳定运行(天)

    提供最优质的资源集合

    立即查看 了解详情