据我所知,在 Go 中模拟结构依赖的唯一方法是使用接口(interface)。所以我的问题是:如果我的结构具有执行某些操作的方法(当结构不仅仅是存储数据的模型时),我是否应该始终将属性定义为接口(interface)以便正确地模拟和测试它?
简单的例子:
type UserService struct {
userRepository UserRepository
}
func (us *UserService) MaleUsers() []User {
all := us.userRepository.FindAll()
maleUsers := []User{}
for _, u := range all {
if u.gender == "male" {
maleUsers = append(maleUsers, u)
}
}
return maleUsers
}
假设我们有一个用户服务,它有一个依赖项:repository。 服务具有获取所有用户然后按某些条件过滤它们的方法。 顺便说一句,过滤逻辑可以放在一个单独的依赖项中,以避免在服务方法 (SRP) 中进行过滤。
顺便说一句。我来自 Java 世界。如果这种构建应用程序的方法在 Go 中不符合概念,请告诉我。
最佳答案
为了模拟 UserService
的 userRepository
依赖项,您认为最好的方法是使用接口(interface)是正确的。
首先,创建您的界面:
type UserRepository interface {
FindAll() []Users
}
然后构建一个模拟:
type MockUserRepository struct{}
func (mock MockUserRepository) FindAll() []Users {
// here you would manually build a slice of users and return it
return []Users
}
最后,在你的测试用例中使用这个 mock 作为依赖:
func TestMaleUsers(t *testing.T) {
// compose service using mock
service := UserService {
userRepository: MockUserRepository,
}
// get output of method call
users := service.MaleUsers()
// perform assertions on output
}
通过这种方式,您已经创建了一个模拟接口(interface),可以在您的测试中使用它,而无需对您的存储库执行任何数据库调用。
关于go - 我是否应该始终将结构属性定义为可测试性的接口(interface)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45262846/