Define interfaces, return structs

I am trying to mock out the MongoDB client library mgo. This library does not seem to use interfaces to define access to its library, so I am trying to mock out the methods our code uses. The problem is when I have a struct that implements a method, but the signature doesn’t match. Easier to grok from the code

Example
type IFoo interface {
	foo() IBar
}

type IBar interface {
	bar()
}

func TakeMyInterface(x IFoo) {
	x.foo().bar()
}

// **********

type SomeUsefulThing struct{}

func (x *SomeUsefulThing) foo() *SomeUsefulThing {
	fmt.Print("SomeUsefulThing::foo was called")
	return x
}
func (x *SomeUsefulThing) bar() {
	fmt.Print("SomeUsefulThing::bar was called")
}

// **********
type MockSomeUsefulThing struct{}

func (x *MockSomeUsefulThing) foo() *MockSomeUsefulThing {
	fmt.Print("MockSomeUsefulThing::foo was called")
	return x
}
func (x *MockSomeUsefulThing) bar() {
	fmt.Print("MockSomeUsefulThing::bar was called")
}

// ********
func main() {
	x := &MockSomeUsefulThing{}
	x.foo().bar()
	TakeMyInterface(x)    <-- This is where I see the error
}

ERROR:
cannot use x (type *MockSomeUsefulThing) as type IFoo in argument to TakeMyInterface:
*MockSomeUsefulThing does not implement IFoo (wrong type for foo method)
have foo() *MockSomeUsefulThing
want foo() IBar

So my problem seems to be that the signature
func (x *MockSomeUsefulThing) foo() *MockSomeUsefulThing
is not the same as
func (x *MockSomeUsefulThing) foo() IBar

But I thought this should work because MockSomeUsefulThing really does implement IBar.

Any thoughts on this would be helpful, since I thought this was a perfectly rational thing to do in Go.

Hi

It works if you define your return type as IBar

func (x *MockSomeUsefulThing) foo() IBar { ... }

Which maybe is what you want. To return something implementing IBar. Or do I missunderstand you?

Thank you for the suggestion. This works fine for my MockSomeUsefulThing, but falls down if I try to pass SomeUsefulThing into TakeMyInterface. In my case SomeUserfulThing is the mongo client class itself, so I cannot alter it.

y :=&SomeUsefulThing{}
y.foo().bar()
TakeMyInterface(y)

Any ideas on how to make this part of it work now?

Do you have a more complete example?

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.