0

我为登录编写了这个 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)
} 
4

1 回答 1

0

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

这个怎么运作

将依赖项传递给 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库。创建一个模拟。

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% 正确的。我自己不使用回声,但它应该让你接近。希望这可以帮助。

于 2021-06-24T00:29:03.077 回答