为了账号安全,请及时绑定邮箱和手机立即绑定

模拟 go 方法

模拟 go 方法

Go
30秒到达战场 2023-04-04 14:39:23
我正在写一个小的 POC 去上班,但我似乎无法弄清楚模拟技术。这是我到目前为止...连接.gopackage dbimport (    "database/sql"    "encoding/json"    "fmt"    "io/ioutil"    "strings"    _ "github.com/lib/pq")type config map[string]interface{}type DbConn struct {    db db}type db interface {    getConnectionStringFromConfig(file string) (connStr string, err error)}func NewDbConn(d db) *DbConn {    return &DbConn{db: d}}func getConnectionStringFromConfig(file string) (connStr string, err error) {    var c config    var bt []byte    if bt, err = ioutil.ReadFile(file); err != nil {        fmt.Printf("Error Reading config file: %v", err)        return    }    fmt.Println("Finish reading file. Going to construct a connection string")    if err = json.Unmarshal(bt, &c); err != nil {        fmt.Printf("Error unmarshalling config file: %v", err)        return    }    connStr = strings.TrimLeft(getConfigAsString(c), " ")    return}func getConfigAsString(c config) (connStr string) {    for k, v := range c {        connStr += strings.Join([]string{" " + k, v.(string)}, "=")    }    return}// Connect database connectionfunc (dbConn DbConn) Connect() (conn *sql.DB, err error) {    fmt.Println("Starting database connection...")    connStr, err := getConnectionStringFromConfig("path/to/conf.json")    if err != nil {        return    }    conn, err = sql.Open("some_driver", connStr)    return}连接测试.gopackage dbimport (    "errors"    "testing")type dbConnMock struct {    db dbMock}type dbMock interface {    getConnectionStringFromConfig(file string) (connStr string, err error)}func (dbm dbConnMock) getConnectionStringFromConfig(file string) (connStr string, err error) {    return "", errors.New("123")}// should not throw error when trying to open db connectionfunc TestDatabaseConnection(t *testing.T) {    dbCon := &DbConn{}    _, err := dbCon.Connect()    if err != nil {        t.Errorf("test failed. \n %d", err)    }}如您所见,这是一个简单的数据库连接逻辑,我使用接口对其进行了测试和模拟。我想覆盖 100% 的代码,所以我必须模拟某些方法。上面的代码虽然有效,但第二个测试失败了,可能是因为我在尝试模拟它时遗漏了一些东西。请帮忙..
查看完整描述

1 回答

?
喵喔喔

TA贡献1735条经验 获得超5个赞

您可以做几件事。


简单的方法

如果你想保持简单,你可以做的是让你的模拟结构具有它应该返回的字段,并且在每个测试用例中你将这些字段设置为你的模拟应该为该测试用例返回的内容。


这样,您可以以不同的方式使模拟成功或失败。


此外,您不需要dbMock接口,因为dbConnMock实现了db接口,这就是您所需要的。


这是您的模拟的样子:


type dbConnMock struct {

    FileCalled string


    connStr string

    err error

}


func (dbm dbConnMock) getConnectionStringFromConfig(file string) (connStr string, err error) {

    dbm.FileCalled = file

    return dbm.connStr, dbm.err

}

现在,您可以通过使用验证您的方法是否使用预期参数调用FileCalled,并且可以使其具有您想要模拟的行为。


如果你还想确保你的方法只被调用一次,你还可以添加一个计数器来查看它被调用了多少次。


使用模拟库

如果您不想担心编写该逻辑,一些库可以为您完成,例如testify/mock。


这是一个简单的模拟如何使用的示例testify/mock:


type dbMock struct {

    mock.Mock

}


func (m *dbMock) getConnectionStringFromConfig(file string) (string, error) {

    args := m.Called(file)


    return args.String(0), args.Error(1)

}


func TestSomething(t *testing.T) {

    tests := []struct {

        description string


        connStr string

        err error


        expectedFileName string


        // add expected outputs and inputs of your tested function

    }{

        {

            description: "passing test",


            connStr: "valid connection string",

            err: nil,


            expectedFileName: "valid.json",

        },

        {

            description: "invalid file",


            connStr: "",

            err: errors.New("invalid file"),


            expectedFileName: "invalid.json",

        },

    }


    for _, test := range tests {

        t.Run(test.description, func(t *testing.T) {


            dbMock := &dbConnectionMock{}

            dbMock.

                On("getConnectionStringFromConfig", test.expectedFileName).

                Return(test.connStr, test.err).

                Once()


            thing := &Something{

                db: dbMock,

            }


            output, err := thing.doSomething()


            // assert that output and err are expected


            dbMock.AssertExpectations(t) // this will make sure that your mock is only used as expected in your test, depending on your `On` calls

        })

    }

}

此代码确保您的方法被调用一次并使用特定参数,并将使其返回测试用例中指定的内容。


查看完整回答
反对 回复 2023-04-04
  • 1 回答
  • 0 关注
  • 115 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信