Is there any way to spy on methods in Golang?
For example, suppose I have
type Object struct {
A int
B string
C *interface{}
}
func (o *Object) Something(val interface{}) {
o.A = 102
// some other business logic under test
o.SomethingElse(o.C, val)
}
//...
func (o *Object) Process(val interface{}) interface{} {
// some business logic
return 43 // or something else. no me importa ya
}
//...
func (o *Object) SomethingElse(iPtr *interface{}, val interface{}) {
processedVal := o.Process(val)
if iPtr == nil {
iPtr = new(interface{})
}
*iPtr = val
}
In writing a test against Object.Something
, we should not need to care about what's happening in SomethingElse
or the Process
invoked from within. Is there any way, in Golang, to isolate these dependencies?
In go you can make functions private (they can only called from the same package) if you write the first letter in lowercase.
If you write the first letter in uppercase you can call the function from everywhere
My understanding of spying is that a single method of an object is faked or mocked while others are not. That's not possible in Go. But you can fake or mock your entire dependencies using interfaces.
In order to fake the SomethingElse
method you would have to put it on another struct separate from your Object
struct. The Object
struct would also need an interface with the SomethingElse
method.
type Object struct {
A int
elser Elser
}
func (o *Object) Something() {
// o.A = 102
o.elser.SomethingElse()
}
type Elser interface {
SomethingElse()
}
Now you can test the Object
behavior by creating a fake that implements the SomethingElse
method:
type fakeElser struct {
somethingElseWasCalled bool
}
func (f *fakeElser) SomethingElse() {
f.somethingElseWasCalled = true
}
func TestSomething(t *testing.T) {
fake := &fakeElser{}
o := &Object{
elser: fake,
}
o.Something()
if o.A != 102 {
t.Errorf("expected A to be %d", 102)
}
if !fake.somethingElseWasCalled {
t.Error("expected SomethingElse to be called")
}
}