使用结构体作为接口而不实现所有方法

huangapple go评论86阅读模式
英文:

Go use struct as interface without implementing all methods

问题

例如,我有一个包含20个方法的UserDao接口。

type UserDao interface {
    GetUser() (User, error)
    GetUsers() ([]User, error)
    ...
}

我想为测试创建一个模拟对象,并且只使用其中一个方法。

type UserDaoMock struct { }

func (UserDaoMock) GetUser() (User, error) {
    return User{}, nil
}

有没有一种方法在将UserDaoMock作为UserDao在测试中使用之前,不需要实现其他方法?告诉编译器这就是应该的方式?

英文:

For example i have dao with 20 methods.

type UserDao interface {
    GetUser() (User, error)
    GetUsers() ([]User, error)
    ...
}

And i want create mock for tests and use only one method.

type UserDaoMock struct { }

fucn (UserDaoMock) GetUser() (User, error) {
    return User{}
}

There is a way to don't implements other methods before using UserDaoMock as a UserDao in tests? Tell the compiler that this is how it should be?

答案1

得分: 13

UserDao接口嵌入到你的模拟结构体中,这样它就会继承所有的方法。只实现你需要的方法(实际上会被调用的方法):

type UserDao interface {
    GetUser() (User, error)
    GetUsers() ([]User, error)
}

type UserDaoMock struct {
    UserDao
}

func (UserDaoMock) GetUser() (User, error) {
    return User{}, nil
}

测试代码:

var dao UserDao
dao = UserDaoMock{}
fmt.Println(dao.GetUser())

输出结果(在Go Playground上尝试):

{} <nil>

请注意,调用其他方法会导致恐慌,因为嵌入的UserDao字段是nil,所以它们背后没有真正的实现。但是UserDaoMock确实实现了UserDao接口,并且GetUser()方法已经实现并可调用。

查看相关问题以检测可调用的方法:https://stackoverflow.com/questions/29988632/go-reflection-with-interface-embedded-in-struct-how-to-detect-real-functions/61448767#61448767

其他相关问题:

https://stackoverflow.com/questions/54128210/is-it-possible-to-define-an-anonymous-interface-implementation-in-go/54128329#54128329

https://stackoverflow.com/questions/48906699/visibility-of-embedded-private-interfaces-in-go/48906742#48906742

英文:

Embed the UserDao interface in your mock struct, so it will have all the methods promoted. Implement only the methods you need (the methods that will actually be called):

type UserDao interface {
	GetUser() (User, error)
	GetUsers() ([]User, error)
}

type UserDaoMock struct {
	UserDao
}

func (UserDaoMock) GetUser() (User, error) {
	return User{}, nil
}

Testing it:

var dao UserDao
dao = UserDaoMock{}
fmt.Println(dao.GetUser())

Which will output (try it on the Go Playground):

{} &lt;nil&gt;

Note that calling any other methods would panic of course, because the embedded UserDao field is nil, so there is no real implementation behind them. But UserDaoMock does implement UserDao, and the GetUser() method is implemented and is callable.

See related question to detect which methods are callable: https://stackoverflow.com/questions/29988632/go-reflection-with-interface-embedded-in-struct-how-to-detect-real-functions/61448767#61448767

Other related questions:

https://stackoverflow.com/questions/54128210/is-it-possible-to-define-an-anonymous-interface-implementation-in-go/54128329#54128329

https://stackoverflow.com/questions/48906699/visibility-of-embedded-private-interfaces-in-go/48906742#48906742

huangapple
  • 本文由 发表于 2022年5月26日 14:30:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/72387640.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定