【问题标题】:How to write Unit test in Golang usng echo for end point url using go mock-gen mocking?如何使用 go mockgen 模拟在 Golang 中使用 echo 为端点 url 编写单元测试?
【发布时间】:2021-09-07 01:00:58
【问题描述】:

我为登录编写了这个 go 代码。现在我想对我的代码进行单元测试。此代码取决于控制器到服务层,然后是服务到存储库层。我想使用 gomock 工具进行模拟,如果有其他请建议我。我正在使用回声框架。 这里

serializers.LoginReq =
{
    Email   string,
    Phone  string,
    Admin  bool 
}
type auth struct {
    authSvc svc.IAuth
    userSvc svc.IUsers
}

func NewAuthController(grp interface {}, authSvc svc.IAuth, userSvc svc.IUsers) {
    ac: = & auth {
        authSvc: authSvc,
        userSvc: userSvc,
    }
    g: = grp.( * echo.Group)
    g.POST("/v1/login", ac.Login)
}


func(ctr * auth) Login(c echo.Context) error {
    var cred * serializers.LoginReq
    var resp * serializers.LoginResp
    var err error

    if err = c.Bind( & cred) err != nil {
        return c.JSON(err.Status, err)
    }
    
    if resp, err = ctr.authSvc.Login(cred); err != nil {
        return c.JSON(err.Status, err)
          }
    return c.JSON(http.StatusOK, resp)
} 

【问题讨论】:

    标签: unit-testing go gomock


    【解决方案1】:

    使用依赖注入。依赖注入是一种设计模式,可以解耦两层或多层软件之间的依赖关系。

    它是如何工作的

    将依赖项传递给 Login 函数。在 Go 中,依赖项通常是接口类型。接口表达了关于其他类型行为的概括或抽象。如果一个类型具有接口中的所有方法,则该类型满足该接口。使用接口,您可以在测试中用假对象(模拟)替换真实对象。只要具体类型满足接口,这不会让 Go 的类型系统抱怨。

    type Auther interface {
      Login(cred *serializers.LoginReq) (*serializers.LoginResp, error)
    }
    

    隐式满足 Go 接口。

    // auth service must implement the Auther interface 
    type auth struct {
        authSvc Auther
    }
    
    // route handler
    func(ctr *auth) Login(c echo.Context) error {
        var cred * serializers.LoginReq
        var resp * serializers.LoginResp
        var err error
    
        if err = c.Bind( & cred) err != nil {
            return c.JSON(err.Status, err)
        }
    
    
        // the function signature of the service-level Login method must match the interface
    
        if resp, err = ctr.authSvc.Login(cred); err != nil {
            return c.JSON(err.Status, err)
              }
        return c.JSON(http.StatusOK, resp)
    } 
    

    我喜欢使用testify/mock 库。创建一个 Mock。

    type MockAuth struct {
      mock.Mock
    }
    
    func (m *MockAuth) Login(cred *serializers.LoginReq) (*serializers.LoginResp, error) {
        args := m.Called(cred)
        return args.Get(0).(*serializers.LoginResp), args.Error(1)
    }
    

    就是这样。只需创建一个测试。

    func TestLogin (t *testing.T) {
        // setup mocks
        cred := &serializers.LoginReq{}
        mockReturn := &serializers.LoginResp{}
        mockAuth := &MockAuth{}
        // setup expectation
        mockAuth.On("Login", cred).Return(mockReturn, nil)
    
        // setup server
        mux := http.NewServeMux()
        mux.HandleFunc("/v1/login", func(w http.ResponseWriter, r *http.Request) {
          ec := echo.Context{}
          ctr: = &auth {
            authSvc: mockAuth
          }
          ctr.Login(ec)
        })
        
        // make request
        writer := httptest.NewRecorder()
        request, _ := http.NewRequest(http.MethodPost, "/v1/login", "password")
        mux.ServeHTTP(writer, request)
        
        // make assertions
        mockAuth.AssertExpectations(t)
        
    }
    
    

    上面的代码不是 100% 正确的。我自己不使用回声,但它应该让你接近。希望这会有所帮助。

    【讨论】:

    • 这里,“ec := echo.Context{}”在这一行给出错误“无效的复合文字类型 echo.Context 编译器无效”
    • 是的,我猜对了。查看文档。 echo.labstack.com/guide/context
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-15
    • 2022-01-24
    • 1970-01-01
    • 1970-01-01
    • 2019-09-13
    • 2015-05-17
    相关资源
    最近更新 更多