Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/grails/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Go 如何在接口内模拟特定的嵌入式方法_Go - Fatal编程技术网

Go 如何在接口内模拟特定的嵌入式方法

Go 如何在接口内模拟特定的嵌入式方法,go,Go,我有这段代码,我想写一个更新函数的单元测试 如何模拟FindByUsername函数 我试图覆盖u.FindByUsername,但它不起作用 此外,我可以编写一些函数,将u*UserLogic和userName string作为输入参数,并执行u.FindByUsername()并模拟此函数,但这不是一个干净的解决方案,我需要一个更好的解决方案来模拟UserOperation接口中的方法 package logic import ( "errors" "fmt" ) var

我有这段代码,我想写一个更新函数的单元测试

如何模拟
FindByUsername
函数

我试图覆盖
u.FindByUsername
,但它不起作用

此外,我可以编写一些函数,将
u*UserLogic
userName string
作为输入参数,并执行
u.FindByUsername()
并模拟此函数,但这不是一个干净的解决方案,我需要一个更好的解决方案来模拟
UserOperation
接口中的方法

package logic

import (
    "errors"
    "fmt"
)

var (
    dataStore = map[string]*User{
        "optic": &User{
            Username: "bla",
            Password: "ola",
        },
    }
)

//UserOperation interface
type UserOperation interface {
    Update(info *User) error
    FindByUsername(userName string) (*User, error)
}

//User struct
type User struct {
    Username string
    Password string
}

//UserLogic struct
type UserLogic struct {
    UserOperation
}

//NewUser struct
func NewUser() UserOperation {
    return &UserLogic{}
}

//Update method
func (u *UserLogic) Update(info *User) error {
    userInfo, err := u.FindByUsername(info.Username)
    if err != nil {
        return err
    }
    fmt.Println(userInfo.Username, userInfo.Password)
    fmt.Println("do some update logic !!!")
    return nil
}

//FindByUsername method
func (u *UserLogic) FindByUsername(userName string) (*User, error) {
    userInfo := &User{}
    var exist bool
    if userInfo, exist = dataStore[userName]; !exist {
        return nil, errors.New("user not found")
    }
    return userInfo, nil
}
更新

我尝试用这段代码模拟函数

func TestUpdate2(t *testing.T) {
    var MockFunc = func(userName string) (*User, error) {
        return &User{Username:"foo", Password:"bar"},nil
    }
    user := NewUser()
    user.FindByUsername = MockFunc
    user.Update(&User{Username:"optic", Password:"ola"})
}

您在
UserOperation
界面中混合了两个抽象级别:
Update
取决于
FindByUsername
。要使
Update
可测试,您需要将
UserFinder
功能注入
Update
方法。您可以这样做,例如通过在
UserLogic
struct中定义一个字段:

type UserOperation interface {
    Update(info *User) error
}

type UserFinder func(userName string) (*User, error)

type UserLogic struct {
    UserOperation
    FindByUsername UserFinder
}

//NewUser struct
func NewUser() *UserLogic { // return structs, accept interfaces!
    return &UserLogic{
        findByUsername: FindByUsername
    }
}

func (u *UserLogic) Update(info *User) error {
    userInfo, err := u.findByUsername(info.Username)
    if err != nil {
        return err
    }
    fmt.Println(userInfo.Username, userInfo.Password)
    fmt.Println("do some update logic !!!")
    return nil
}

func FindByUsername(userName string) (*User, error) {
    userInfo := &User{}
    var exist bool
    if userInfo, exist = dataStore[userName]; !exist {
        return nil, errors.New("user not found")
    }
    return userInfo, nil
}

您在
UserOperation
界面中混合了两个抽象级别:
Update
取决于
FindByUsername
。要使
Update
可测试,您需要将
UserFinder
功能注入
Update
方法。您可以这样做,例如通过在
UserLogic
struct中定义一个字段:

type UserOperation interface {
    Update(info *User) error
}

type UserFinder func(userName string) (*User, error)

type UserLogic struct {
    UserOperation
    FindByUsername UserFinder
}

//NewUser struct
func NewUser() *UserLogic { // return structs, accept interfaces!
    return &UserLogic{
        findByUsername: FindByUsername
    }
}

func (u *UserLogic) Update(info *User) error {
    userInfo, err := u.findByUsername(info.Username)
    if err != nil {
        return err
    }
    fmt.Println(userInfo.Username, userInfo.Password)
    fmt.Println("do some update logic !!!")
    return nil
}

func FindByUsername(userName string) (*User, error) {
    userInfo := &User{}
    var exist bool
    if userInfo, exist = dataStore[userName]; !exist {
        return nil, errors.New("user not found")
    }
    return userInfo, nil
}

您想模拟该函数以便测试更新吗?你试过什么不起作用的?是的,我试着模仿``func TestUpdate(t*testing.t){var MockFunc=func(用户名字符串)(*User,error){return&User{userName:“foo”,Password:“bar”},nil}User:=NewUser()User.FindByUsername=MockFunc User.Update(&User{userName:“optic”,Password:“ola”})```但它不起作用。请不要在注释中添加代码,而是更新您的问题。不能将函数分配给Go中的方法。您可以编写接口
UserOperation
的模拟实现,并在测试过程中使用它。@请看一看:尽管这不是真正的模拟,但我将其称为假或存根,mock通常允许您指定希望调用的方法及其参数和返回值,然后在测试结束时检查它们是否实际被调用。您可能想尝试一下:您想模拟该函数以便测试更新吗?你试过什么不起作用的?是的,我试着模仿``func TestUpdate(t*testing.t){var MockFunc=func(用户名字符串)(*User,error){return&User{userName:“foo”,Password:“bar”},nil}User:=NewUser()User.FindByUsername=MockFunc User.Update(&User{userName:“optic”,Password:“ola”})```但它不起作用。请不要在注释中添加代码,而是更新您的问题。不能将函数分配给Go中的方法。您可以编写接口
UserOperation
的模拟实现,并在测试过程中使用它。@请看一看:尽管这不是真正的模拟,但我将其称为假或存根,mock通常允许您指定希望调用的方法及其参数和返回值,然后在测试结束时检查它们是否实际被调用。您可能想尝试一下: