如何在测试中将模型与控制器分开?

所以我想在测试中将控制器与模型隔离,这样我就可以在出现问题时轻松解决问题。之前,我只是使用模拟数据访问端点,但很难排除故障,因为测试从路由器一直运行到数据存储。所以我想也许我会为每个控制器(和模型)创建两个版本(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)

}

这样我就可以跳过 sql 查询MockUserController.Login(),只验证有效负载并返回有效响应。


你觉得这个设计怎么样?你有更好的实现吗?


慕森王
浏览 181回答 2
2回答

慕码人2483693

我会让调用 NewUserController() 和 NewUserModel() 的代码决定是创建模拟还是真实实现。如果您一直使用这种依赖注入模式直到顶部,您的代码将变得更清晰,耦合度也会降低。例如,如果用户控制器被服务器使用,它看起来像这样:真实:u := NewUserController() s := NewServer(u)在测试中:u := NewMockUserController() s := NewServer(u)

慕沐林林

我会尝试一个更纤薄的变体,分布在模型和控制器包上,如下所示:// inside package controllerstype UserModel interface {    Get() // the methods you need from the user model}type User struct {    UserModel}// inside package modelstype User struct {    // here the User Model}// inside package mainimport ".....controllers"import ".....models"func main() {    c := &controllers.User{&models.User{}}}// inside main_test.goimport ".....controllers"type MockUser struct {}func TestX(t *testing.T) {    c := &controllers.User{&MockUser{}}}对于控制器测试,请考虑httptest 包的ResponseRecorder
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go