как заглушить метод, вызываемый другим методом, в той же структуре - PullRequest
1 голос
/ 27 мая 2020

Код здесь:

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
}

Теперь я хочу протестировать метод Pool структуры Connector. Поскольку метод ping имеет некоторую побочную операцию RP C, мне нужно заглушить его и его возвращаемое значение, чтобы я мог протестировать каждую ветвь кода в методе 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")

1 Ответ

0 голосов
/ 04 сентября 2020

Нам нужно следовать Принципу инверсии зависимостей , это упростит тестирование кода.

Детали (конкретные реализации) должны зависеть от абстракций.

Реорганизованный код:

connector.go:

package connector

import (
    "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
}

Теперь создайте имитацию БД, которая реализует интерфейс Pinger с помощью пакета stretchr / testify . Затем передайте эту фиктивную БД в структуру Connector, это своего рода инъекция зависимостей.

Затем мы можем «имитировать» Ping метод с разными возвращаемыми значениями.

connector_test.go:

package connector_test

import (
    "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_alive
success logic
=== RUN   TestConnector_Pool/should_return_error_if_connection_to_the_database_is_not_alive
error 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)
PASS
coverage: 100.0% of statements
ok      github.com/mrdulin/golang/src/stackoverflow/62035606    0.364s

Отчет о покрытии:

введите описание изображения здесь

...