go icon indicating copy to clipboard operation
go copied to clipboard

x/tools/gopls: code action to extracting an interface for usage

Open js-sketch opened this issue 4 years ago • 1 comments

Consider the following program:

type bar struct {}
func (b *bar) x() {}
func (b *bar) y() {}
type Foo struct {
    bar *bar
}
func (f *Foo) baz() {
    f.b.y()
}

Now assume we would like to test foo and for this we'd want to mock bar. The recommended way of doing this is to extract the way that bar is used into an interface and use that in lieu of bar in foo.

type bar struct {}
func (b *bar) x() {}
func (b *bar) y() {}

type barI interface {
    y()
}
type Foo struct {
    bar barI
}
func (f *Foo) baz() {
    f.b.y()
}

Note that only y() was extracted. Supporting such a code action in gopls would make life a lot easier for devs who write unit tests. This is at least viable to implement for unexported members, as no new methods can be added in other packages which access this member.

js-sketch avatar Jun 09 '21 08:06 js-sketch

Thanks for the feature request. I agree that this could be a useful refactoring operation, and is certainly doable. It's also useful for more than just testing.

findleyr avatar Jun 09 '21 17:06 findleyr