猿问

如何在同一结构中的另一个方法中调用存根方法

代码在这里:


package main


import (

  "fmt"

)


type Connector struct {}


func (c *Connector) Pool() (interface{}, error) {

  err := c.ping()

  if err != nil {

    fmt.Println("error handle logic");

    return nil, err

  }

  fmt.Println("success logic")

  return 1, nil

}


func (c *Connector) ping() error {

  var err error

  // err = some side-effect RPC operation

  if err != nil {

    return err

  }

  return nil

}

现在,我想测试一下struct的Pool方法。Connector由于该ping方法有一些副作用 RPC 操作,我需要对它及其返回值进行存根,以便我可以测试该Pool方法中的每个代码分支。


成功测试用例伪代码:


Stub(c, "ping").Return(nil)

c.Pool()

Expect(fmt.Println).ToBeCalledWith("success logic")

失败测试用例伪代码:


Stub(c, "ping").Return(errors.New("test"))

c.Pool()

Expect(fmt.Println).ToBeCalledWith("error handle logic")


一只斗牛犬
浏览 145回答 1
1回答

慕桂英546537

我们需要遵循依赖倒置原则,这将使代码更容易测试。细节(具体实现)应该依赖于抽象。重构代码:connector.go:package connectorimport (    "fmt")type Pinger interface {    Ping() error}type Connector struct {    DB Pinger}func (c *Connector) Pool() (interface{}, error) {    err := c.DB.Ping()    if err != nil {        fmt.Println("error handle logic")        return nil, err    }    fmt.Println("success logic")    return 1, nil}现在,使用stretchr/testify包创建实现Pinger接口的模拟数据库。然后,将这个模拟的 DB 传递给struct,这是某种依赖注入。Connector然后我们可以“模拟”Ping具有不同返回值的方法。connector_test.go:package connector_testimport (    "fmt"    "testing"    connector "github.com/mrdulin/golang/src/stackoverflow/62035606"    "github.com/stretchr/testify/mock"    "github.com/stretchr/testify/require")type MockedDB struct {    mock.Mock}func (db *MockedDB) Ping() error {    args := db.Called()    return args.Error(0)}func TestConnector_Pool(t *testing.T) {    t.Run("should verifies connection to the database is still alive", func(t *testing.T) {        testDB := new(MockedDB)        c := connector.Connector{DB: testDB}        testDB.On("Ping").Return(nil)        pool, err := c.Pool()        require.Nil(t, err, nil)        require.Equal(t, 1, pool)    })    t.Run("should return error if connection to the database is not alive", func(t *testing.T) {        testDB := new(MockedDB)        c := connector.Connector{DB: testDB}        testDB.On("Ping").Return(fmt.Errorf("network"))        pool, err := c.Pool()        require.Error(t, err, "network")        require.Nil(t, pool)    })}单元测试结果:=== RUN   TestConnector_Pool=== RUN   TestConnector_Pool/should_verifies_connection_to_the_database_is_still_alivesuccess logic=== RUN   TestConnector_Pool/should_return_error_if_connection_to_the_database_is_not_aliveerror handle logic--- PASS: TestConnector_Pool (0.00s)    --- PASS: TestConnector_Pool/should_verifies_connection_to_the_database_is_still_alive (0.00s)    --- PASS: TestConnector_Pool/should_return_error_if_connection_to_the_database_is_not_alive (0.00s)PASScoverage: 100.0% of statementsok      github.com/mrdulin/golang/src/stackoverflow/62035606    0.364s覆盖报告:
随时随地看视频慕课网APP

相关分类

Go
我要回答