为了账号安全,请及时绑定邮箱和手机立即绑定

如何在 golang 中测试映射对象

如何在 golang 中测试映射对象

Go
胡子哥哥 2023-03-15 14:41:21
我尝试在我的 go 代码中实现一些单元测试,发现模拟方法的主题非常困难。我有以下示例,希望您能帮助我 :)在第一层我有以下代码:package apiimport (    "fmt"    "core")type createUserDTO struct {    Id string}func ApiMethod() {    fmt.Println("some incoming api call wit user")    incomingUserData := &createUserDTO{Id: "testId"}    mapedUser := incomingUserData.mapUser()    mapedUser.Create()}func (createUserDTO *createUserDTO) mapUser() core.User {    return &core.UserCore{Id: createUserDTO.Id}}第二层有如下代码:package coreimport (    "fmt")type CoreUser struct{ Id string }type User interface {    Create()}func (user CoreUser) Create() {    fmt.Println("Do Stuff")}我现在的问题是,如何在不测试核心包的情况下测试 api 包中的每个公共方法。特别是方法 Create()。
查看完整描述

1 回答

?
胡说叔叔

TA贡献1804条经验 获得超8个赞

根据评论,我整理了一个简单的 GitHub 存储库来展示我通常如何处理 Go 中的结构化项目。存储库暂时不考虑测试部分,但使用此项目结构插入它们应该很容易。
让我们从一般文件夹的布局开始:

  • controllers

  • services

  • db

  • dto

  • models

现在,让我们看看相关文件。

models/user.go

package models


import "gorm.io/gorm"


type User struct {

    *gorm.Model

    Id string `gorm:"primaryKey"`

}


func NewUser(id string) *User {

    return &User{Id: id}

}

简单的结构定义在这里。


dto/user.go

package dto


import "time"


type UserDTO struct {

    Id      string    `json:"id"`

    AddedOn time.Time `json:"added_on"`

}


func NewUserDTO(id string) *UserDTO {

    return &UserDTO{Id: id}

}

我们用一个虚拟字段来丰富模型结构,AddedOn这只是为了演示。


db/user.go

package db


import (

    "gorm.io/gorm"


    "userapp/models"

)


type UserDb struct {

    Conn *gorm.DB

}


type UserDbInterface interface {

    SaveUser(user *models.User) error

}


func (u *UserDb) SaveUser(user *models.User) error {

    if dbTrn := u.Conn.Create(user); dbTrn.Error != nil {

        return dbTrn.Error

    }

    return nil

}

在这里,我们定义了一个使用User存储库的接口。在我们的测试中,我们可以提供模拟而不是UserDb结构的实例。


services/user.go

package services


import (

    "time"


    "userapp/db"

    "userapp/dto"

    "userapp/models"

)


type UserService struct {

    DB db.UserDbInterface

}


type UserServiceInterface interface {

    AddUser(inputReq *dto.UserDTO) (*dto.UserDTO, error)

}


func NewUserService(db db.UserDbInterface) *UserService {

    return &UserService{

        DB: db,

    }

}


func (u *UserService) AddUser(inputReq *dto.UserDTO) (*dto.UserDTO, error) {

    // here you can write complex logic

    user := models.NewUser(inputReq.Id)


    // invoke db repo

    if err := u.DB.SaveUser(user); err != nil {

        return nil, err

    }


    inputReq.AddedOn = time.Now()


    return inputReq, nil

}

这是桥接表示层和底层存储库之间连接的层。


controllers/user.go

package controllers


import (

    "encoding/json"

    "io"

    "net/http"


    "userapp/dto"

    "userapp/services"

)


type UserController struct {

    US services.UserServiceInterface

}


func NewUserController(userService services.UserServiceInterface) *UserController {

    return &UserController{

        US: userService,

    }

}


func (u *UserController) Save(w http.ResponseWriter, r *http.Request) {

    reqBody, err := io.ReadAll(r.Body)

    if err != nil {

        panic(err)

    }

    r.Body.Close()


    var userReq dto.UserDTO


    json.Unmarshal(reqBody, &userReq)


    userRes, err := u.US.AddUser(&userReq)

    if err != nil {

        w.WriteHeader(http.StatusInternalServerError)

        json.NewEncoder(w).Encode(err)

        return

    }


    w.WriteHeader(http.StatusCreated)

    json.NewEncoder(w).Encode(userRes)

}

在这里,我们定义了(通过依赖注入)使用UserService结构的控制器。


您可以在我的GitHub存储库中找到所有内容 如果它能澄清一点,请告诉我。



查看完整回答
反对 回复 2023-03-15
  • 1 回答
  • 0 关注
  • 96 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信