Testing 当一个具体方法的签名引用另一个具体类型而不是其接口时,如何模拟多个类型?

Testing 当一个具体方法的签名引用另一个具体类型而不是其接口时,如何模拟多个类型?,testing,go,mocking,Testing,Go,Mocking,我正在使用一个第三方库,它的类没有任何接口。我可以毫无问题地在我的结构中使用它们,但它们有一些副作用,我希望在进行单元测试时避免这些副作用 // Somewhere there are a couple structs, with no interfaces. I don't own the code. // Each has only one method. type ThirdPartyEntry struct {} func (e ThirdPartyEntry) Resolve() st

我正在使用一个第三方库,它的类没有任何接口。我可以毫无问题地在我的结构中使用它们,但它们有一些副作用,我希望在进行单元测试时避免这些副作用

// Somewhere there are a couple structs, with no interfaces. I don't own the code.
// Each has only one method.
type ThirdPartyEntry struct {}
func (e ThirdPartyEntry) Resolve() string {
    // Do some complex stuff with side effects
    return "I'm me!"
}

// This struct returns an instance of the other one.
type ThirdPartyFetcher struct {}
func (f ThirdPartyFetcher) FetchEntry() ThirdPartyEntry {
    // Do some complex stuff with side effects and return an entry
    return ThirdPartyEntry{}
}

// Now my code.
type AwesomeThing interface {
    BeAwesome() string
}
// I have a class that makes use of the third party.
type Awesome struct {
    F ThirdPartyFetcher
}
func (a Awesome) BeAwesome() string {
    return strings.Repeat(a.F.FetchEntry().Resolve(), 3)
}
func NewAwesome(fetcher ThirdPartyFetcher) Awesome {
    return Awesome{
        F: fetcher,
    }
}

func main() {
    myAwesome := NewAwesome(ThirdPartyFetcher{})
    log.Println(myAwesome.BeAwesome())
}
这管用!但是我想写一些单元测试,所以我想模拟第三方结构。要做到这一点,我相信我需要为它们提供接口,但由于ThirdPartyFetcher返回ThirdPartyEntry,我不知道如何返回

我创建了一对与两个第三方类匹配的接口。然后我想重写Awesome结构和方法,以使用通用的Fetcher接口。在我的测试中,我将调用NewAwesome()传入testFetcher,这是一个也实现接口的结构

type Awesome struct {
    F Fetcher
}
func NewAwesome(fetcher Fetcher) Awesome {
    return Awesome{
        Fetcher: fetcher,
    }
}

type Entry interface {
    Resolve() string
}
// Double check ThirdPartyEntry implements Entry
var _ Entry = (*ThirdPartyEntry)(nil)

type Fetcher interface {
    FetchEntry() Entry
}
// Double check ThirdPartyFetcher implements Fetcher
var _ Fetcher = (*ThirdPartyFetcher)(nil)
我省略了测试代码,因为它不相关。这在显示的最后一行失败

./main.go:49: cannot use (*ThirdPartyFetcher)(nil) (type *ThirdPartyFetcher) as type Fetcher in assignment:
*ThirdPartyFetcher does not implement Fetcher (wrong type for FetchEntry method)
    have FetchEntry() ThirdPartyEntry
    want FetchEntry() Entry

签名是不同的,尽管我已经展示了ThirdPartyEntry实现了Entry。我认为这是不允许的,因为to会导致类似于切片的东西(在多态意义上,而不是golang意义上)。我有没有办法写一对接口?在这种情况下,Awesome类甚至不知道ThirdParty的存在——它被抽象在接口后面,并在main调用NewAwesome时被注入。

这不是很漂亮,但一种方法是:

type fetcherWrapper struct {
    ThirdPartyFetcher
}

func (fw fetcherWrapper) FetchEntry() Entry {
    return fw.ThirdPartyFetcher.FetchEntry()
}

我想说,模仿返回结构与接口的东西是一个相对常见的问题,除了大量的中间包装之外,没有任何好的解决方案。

谢谢@AlexGuerra。您正在确认我从其他来源听到的消息,这似乎是我测试的最佳选择。