2014-10-27 82 views
0

所以我想在测试中将控制器与模型隔离开来,以便在出现问题时能够轻松找出问题。之前,我只是用模拟数据命中端点,但难以排除故障,因为测试从路由器一直运行到数据存储。所以我想也许我会为每个控制器(和模型)创建两个版本(MockController vs Controller),并根据模式变量的值使用一个版本。简而言之,这是我计划实施它的方式。如何在测试中将模型与控制器分开?

const mode string = "test" 

// UserModelInterface is the Interface for UserModel 
type UserModelInterface interface { 
    Get() 
} 

// UserControllerInterface is the Interface for UserController 
type UserControllerInterface interface { 
    Login() 
} 

// NewUserModel returns a new instance of user model 
func NewUserModel() UserModelInterface { 
    if mode == "test" { 
     return &MockUserModel{} 
    } else { 
     return &UserModel{} 
    } 
} 

// NewUserController returns a new instance of user controller 
func NewUserController(um UserModelInterface) UserControllerInterface { 
    if mode == "test" { 
     return &MockUserController{} 
    } else { 
     return &UserController{} 
    } 
} 

type (
    UserController struct {um UserModelInterface} 
    UserModel struct {} 

    // Mocks 
    MockUserController struct {um UserModelInterface} 
    MockUserModel struct {} 
) 

func (uc *UserController) Login() {} 
func (um *UserModel) Get() {} 

func (uc *MockUserController) Login() {} 
func (um *MockUserModel) Get() {} 

func main() { 
    um := NewUserModel() 
    uc := NewUserController(um) 
} 

这样我可以只跳过了MockUserController.Login() SQL查询,只验证有效载荷,并返回一个有效的响应。

您对这种设计有什么看法?你有更好的实施?

+0

为什么不使用建立标签做你需要什么? – Peter 2014-10-27 04:35:39

回答

0

我会让调用NewUserController()和NewUserModel()的代码决定是创建一个模拟还是真实的实现。如果您一直使用这种依赖注入模式,则代码将变得更清晰,耦合也更少。例如。如果用户控制器由服务器使用,它看起来像沿着线:

真:

U:= NewUserController() S:= NEWSERVER(U)

在测试中:

U:= NewMockUserController() S:= NEWSERVER(U)

0

我会尝试在车型更加纤薄变种传播和控制器包,就像这样:

// inside package controllers 

type UserModel interface { 
    Get() // the methods you need from the user model 
} 

type User struct { 
    UserModel 
} 

// inside package models 

type User struct { 
    // here the User Model 
} 


// inside package main 

import ".....controllers" 
import ".....models" 

func main() { 
    c := &controllers.User{&models.User{}} 
} 

// inside main_test.go 
import ".....controllers" 

type MockUser struct { 

} 


func TestX(t *testing.T) { 
    c := &controllers.User{&MockUser{}} 
} 

控制器测试中考虑ResponseRecorder of httptest package