Testing

PEAR2020發表於2024-06-21

1. use mock data

假設需要測試一個介面,並不希望有data層面的互動(test方法中需要初始化db等配置)

首先需要改造UserServer, 讓 userData interface 注入,然後我可以實現userDataImpl (有*gorm.db注入),也可以實現mockDataimpl(內建map,記憶體儲存資料)

type UserServer struct {
    proto.UnimplementedUserServer
    db UserData
}

// data interface
type UserData interface {
  // handler中和databse互動的方法 GetUserByMobile(ctx context.Context, mobile
string) (User, error) // 這個方法查詢出來後用來注入空User中,所以返回User Create(user User) (tx *gorm.DB) } // mock the data tier for test type userDataMock struct { userinfo map[string]User } func (u *userDataMock) GetUserByMobile(ctx context.Context, mobile string) (User, error) { return u.userinfo[mobile], nil } func (u *userDataMock) Create(user User) (tx *gorm.DB) { u.userinfo[user.Mobile] = user return nil } // impl the data tier, need db type userDataImpl struct { db *gorm.DB } func (u *userDataImpl) GetUserByMobile(ctx context.Context, mobile string) (User, error) { return User{}, nil } func (u *userDataImpl) Create(user *User) (tx *gorm.DB) { return u.db.Create(&user) } // init the impl func NewUserDataMock() *userDataMock { return &userDataMock{userinfo: make(map[string]User)} } func NewUserData(db *gorm.DB) *userDataImpl { return &userDataImpl{db: db} }

handler方法:

func (s *UserServer) CreateUser(ctx context.Context, req *proto.CreateUserInfo) (*proto.UserInfoRsp, error) {
    var user User
    user, _ = s.db.GetUserByMobile(ctx, req.Mobile) // UserServer的userData interface,適配mock資料需求和正常db連線需求
    //result := s.db.Where(&User{Mobile: req.Mobile}).First(&user)
    //if result.RowsAffected == 1 {
    //    return nil, status.Errorf(codes.AlreadyExists, "user already exists")
    //}
    user.Mobile = req.Mobile
    user.NickName = req.NickName

    options := &password.Options{16, 100, 30, sha512.New}
    salt, encodedPwd := password.Encode("generic password", options)
    user.Password = fmt.Sprintf("$sha512$%s$%s", salt, encodedPwd)
    //result = global.DB.Create(&user)
    //if result.Error != nil {
    //    return nil, status.Errorf(codes.Internal, result.Error.Error())
    //}
    _ = s.db.Create(user)
    // create user後database生成id -> 返回給呼叫方
    rsp := ModelToRsp(user)
    return &rsp, nil
}

相關文章