在void函数中使用的结构上模拟复杂方法

My problem isn't terribly complex. I'll write a simple example first, and then show the real code after in case I missed any subtleties.

So I have a third-party library:

// Third party library
type ThirdPartyFoo struct {}    
func (t *ThirdPartyFoo) DoFoo () *ThirdPartyFoo {
    println("I'm a third party library!")
    return t
}

And I want to use that library to invoke DoFoo():

type MyThing struct {
    TheFoo ThirdPartyFoo
}

func (myThing *MyThing) WhichLib () {
    myThing.TheFoo.DoFoo()
}

And I want to test it with a mocked version of ThirdPartyFoo because, how else am I supposed to verify that DoFoo() was A) invoked, B) invoked with the correct parameters, and C) MyThing responds correctly based on different return values?

I tried using an interface inside MyThing instead of directly depending on ThirdPartyFoo...

type IThirdPartyFoo interface {
    DoFoo() *IThirdPartyFoo
}

type MyThingWithI struct {
    TheFoo IThirdPartyFoo
}

func (myThing *MyThingWithI) WhichLib () {
    myThing.TheFoo.DoFoo()
}

And then invoking the function...

func main() {
    realFoo := ThirdPartyFoo{}
    realThing := MyThingWithI{
        TheFoo: &realFoo,
    }
    realThing.WhichLib()
}

But it fails at runtime:

proxyutils/serviceregistrar.go:44:9: cannot use &realFoo (type *ThirdPartyFoo) as type IThirdPartyFoo in field value:
        *ThirdPartyFoo does not implement IThirdPartyFoo (wrong type for DoFoo method)
                have DoFoo() *ThirdPartyFoo
                want DoFoo() IThirdPartyFoo

So... I've spent a couple hours trying to figure this out, and another hour writing up this post... and I'm still lost. The only solution I can come up with is to completely wrap the third party library, like so:

type IThirdPartyFooWrapper interface {
    DoFoo() IThirdPartyFooWrapper
}

type ThirdPartyFooWrapper struct {
    IThirdPartyFooWrapper

    ThirdPartyFoo ThirdPartyFoo
}

func (w *ThirdPartyFooWrapper) DoFoo () IThirdPartyFooWrapper {
    w.ThirdPartyFoo.DoFoo()
    return w
}

type MyThingWithI struct {
    TheFooWrapper IThirdPartyFooWrapper
}

func (myThing *MyThingWithI) WhichLib() {
    myThing.TheFooWrapper.DoFoo()
}

But there are SO MANY levels of indirection already that I really hate to add this one. This is what mocking was made for, but it seems the Go language has completely screwed over any poor schmuck unfortunate enough to have started using a third-party library that isn't making use of interfaces.

And finally, here's my real code. It's the *mux.Router as part of ServiceRegistrar that is being problematic.

package proxyutils

import (
    "errors"
    "github.com/gorilla/mux"
    "net/http"
)

type IProxyRegistrar interface {
    Register(input Registration) error
}

type ServiceRegistrarFactory struct{}

func (_ *ServiceRegistrarFactory) Build(proxyRegistrar IProxyRegistrar, router *mux.Router) (*ServiceRegistrar, error) {
    if nil == proxyRegistrar {
        return nil, errors.New("cannot create ServiceRegistrar with nil IProxyRegistrar")
    }
    if nil == router {
        return nil, errors.New("cannot create ServiceRegistrar with nil mux.Router")
    }
    return &ServiceRegistrar{
        proxyRegistrar: proxyRegistrar,
        router:         router,
    }, nil
}

type ServiceRegistrar struct {
    proxyRegistrar IProxyRegistrar
    router         *mux.Router
}

func (r *ServiceRegistrar) Register(userRegistration Registration, f func(http.ResponseWriter, *http.Request)) error {
    err := r.proxyRegistrar.Register(userRegistration)
    if nil == err {
        var route *mux.Route
        if userRegistration.PathIsPrefix {
            route = r.router.PathPrefix(userRegistration.Path)
        } else {
            route = r.router.Path(userRegistration.Path)
        }
        route.Methods(userRegistration.Methods...).HandlerFunc(f)
        return nil
    } else {
        return err
    }
}