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)
}