Go测试包中的模拟statsd客户端

I use this statsd package to send metrics to our statsd server. To initialize the client, I call a metrics.Setup() in my main which does the init. This package looks like this:

package:

package metrics

import (
    "fmt"

    "github.com/cactus/go-statsd-client/statsd"
)

// Client can be used to send stats to
var Client StatsdAccess

// Setup initialises metrics gathering
func Setup() {
    if Client == nil {
        prefix := fmt.Sprintf("app.%s", logging.GetHost())
        std, err := statsd.NewBufferedClient(fmt.Sprintf("localhost:1234", prefix, 0, 0)
        if err != nil {
            logrus.Errorf("unable to dial the statsd host: %q", err)
            return
        }
        Client = std
    }
}

// StatsdAccess is used as interface to statsd functions
type StatsdAccess interface {
    Inc(stat string, value int64, rate float32) error
    Gauge(stat string, value int64, rate float32) error
    Timing(stat string, delta int64, rate float32) error
}

From this moment on, the other package send metrics though this global Client by doing this: metrics.Client.Inc("some.counter", 1, 1.0). This works fine, but now I have a problem with my test files. They now fail when a package actually uses the metrics package to send metrics. This is obvious, because the metrics package has not been initialized, etc. So my question -I think- is: how can I mock the statsd client in my test files?

Many of the project I work on use statsd and have teetered between just leaving the calls in the tests, because they are so lightweight, and programming to a metrics interface (as you have already done StasdAccess).

Since the interface is already initialized, you should be able to use the interface to break the configuration dependency in your code, and provide a test implementation to use in your tests:

package_metrics/
   testing.go

// testing.go

type StubStatsd struct {}
func (s StubStatsd) Inc(stat string, value int64, rate float32) error {
  return nil
}
func (s StubStatsd) Gauge(...
func (s StubStatsd) Timing(...

Now when your tests would like to call a method or initialize a component that requires a StatsdAccess parameter it could use the testing stub to meet the requirements

func TestSomething_NeedsStatsd(t *testing.T) {
     statsdStub := StubStatsd{}
     someMethodThatRequiresStatsd(stasdStub)
}