【发布时间】:2021-09-16 11:01:30
【问题描述】:
我想为我的 http 处理程序构建一个测试部分,并且我想按原样使用 http 处理程序函数,但我想有单独的函数来模拟处理的 db 部分。我的想法是这样的:
package main
import (
"log"
"testing"
)
// DB functions
type UserDBFunctions interface {
InsertUser() string
}
type UserDB struct {
}
func (u UserDB) InsertUser() string {
return "hello"
}
// http handler functions
type UserHandlerFunctions interface {
Register() string
}
type UserHandler struct {
userDb *UserDB
}
func newUserHandler() UserHandler {
return UserHandler{userDb: new(UserDB)}
}
func (u UserHandler) Register() string {
str := u.userDb.InsertUser()
return str + " world"
}
func main() {
var i UserHandlerFunctions = newUserHandler()
str := i.Register()
log.Println(str)
}
// test functions
type FakeUserDBFunctions interface {
InsertUser() string
}
type FakeUserDB struct {
}
func (u FakeUserDB) InsertUser() string {
return "bye"
}
func newFakeUserHandler() UserHandler {
return UserHandler{userDb: *UserDB(&FakeUserDB{})}
}
func TestRegisterUser(t *testing.T) {
t.Run("register user", func(t *testing.T) {
var i UserHandlerFunctions = newFakeUserHandler()
str := i.Register()
log.Println(str)
})
}
所以第一个接口是真正的 db 函数,然后是调用 db 函数的 http 处理程序,在 main() 函数下面应该是带有 db 函数模型的测试。但这部分不起作用。如何用模型替换 newUserHandler 中的真实接口。
非常感谢您的帮助。 ????
【问题讨论】:
-
我认为你做的有点不对。 IMO 一个更经典的方法是拥有一个接口“用户数据库”,它必须由您的“真实”
UserDB类型和一些在测试中实例化的存根/模拟/假类型来实现。你的其余代码——一个特定的 HTTP 服务器多路复用器或其他任何东西——在构建时提供了一个实现该“用户数据库”接口的类型的实例,并且完全忘记了它所使用的实例的真正动态类型;多路复用器的处理程序——也是。然后,您可以使用处理程序并酌情检查结果。 -
我无法想象你的结构。我想要一个 userHandler,它有多个处理函数,比如
func (u User) RegisterUser(rw ..., r ...) {...},并且 userHandler 结构用一个服务结构初始化,我用它来初始化数据库、AuthMiddleware 等,我可以将它重用于所有服务。现在我已经将数据库逻辑与 http 处理(例如检查值等)分开了。 -
我想在不使用数据库的情况下测试 http 处理程序。但我只需要 db 部分中的上述服务结构,我想模拟它以进行 http 处理程序测试。这就是为什么我要构建一个新的 FakeUserDB。
-
这里是一个例子:play.golang.org/p/sgV3sni0BDd
标签: go testing struct interface