'How to mock a file with interface imported from another file
I try to create a mock of a file with an interface imported from another file. I have try with `aux_files` and `imports` but I did non succeed to have a correct mock file. I think I'm missing something.
So I have a `mockgen/main.go` like this :
package main
import (
"log"
o "mockgen/otheri"
)
type bar struct {
a o.Foo
}
func NewBar(a o.Foo) *bar {
return &bar{a}
}
func main() {
var t = NewBar(&o.FunctionStuct{})
if err := t.a.Ask(); err != nil {
log.Fatal(err)
}
}
And the interface imported is in `mockgen/otheri/otheri.go` :
package otheri
import "log"
type Foo interface {
Ask() error
}
type FunctionStuct struct {
}
func (f *FunctionStuct) Ask() error {
log.Println("Hello")
return nil
}
The command I tried is : mockgen -source main.go -aux_files o=otheri/otheri.go
executed at the same level as the main.go
But my mockgen file is empty....
Does anyone has an idea ? My goal is to mock the interface o.Foo contains in main.go me without changing my architecture
I need to mock it to test it with unit tests.
The architecture is like this because I follow clean architecture.
Thanks for all
Solution 1:[1]
You can generate mocks only for interfaces. So, in your example you should run mockgen for file mockgen/otheri/otheri.go because target interface presented where.
But as Elias Van Ootegem pointed out, it's a bad practice to have an interface with the struct which conforming it. You should separate interface and implementation. So, it should be smth like:
File /bar/bar.go
package bar
import (
"log"
)
type Foo interface {
Ask() error
}
type bar struct {
foo Foo
}
func NewBar(a Foo) *bar {
return &bar{a}
}
func (b *bar) Ask() {
if err := b.foo.Ask(); err != nil {
log.Fatal(err)
}
}
File otheri/otheri.go
package otheri
import "log"
type FunctionStruct struct {
}
func (f *FunctionStruct) Ask() error {
log.Println("Hello")
return nil
}
File main.go
package main
import (
"bar"
"otheri"
)
func main() {
fs := &otheri.FunctionStruct{}
b := bar.NewBar(fs)
b.Ask()
}
And generate a mock mockgen -source=bar/bar.go -destination=bar/mock/foo_mock.go Foo
Furthermore, follow the rules described in effective go the best way to use your FunctionStruct - hide the type in the package:
If a type exists only to implement an interface and will never have exported methods beyond that interface, there is no need to export the type itself
So, the final solution will move interface to a separate package:
File /foo/foo.go
package foo
type Foo interface {
Ask() error
}
File /bar/bar.go
package bar
import (
"log"
"foo"
)
type bar struct {
foo foo.Foo
}
func NewBar(a foo.Foo) *bar {
return &bar{a}
}
func (b *bar) Ask() {
if err := b.foo.Ask(); err != nil {
log.Fatal(err)
}
}
File otheri/otheri.go
package otheri
import (
"log"
"foo"
)
func New() foo.Foo {
return &functionStruct{}
}
type functionStruct struct {
}
func (f *functionStruct) Ask() error {
log.Println("Hello")
return nil
}
File main.go
package main
import (
"bar"
"otheri"
)
func main() {
b := bar.NewBar(otheri.New())
b.Ask()
}
And mockgen: mockgen -source=foo/foo.go -destination=foo/mock/foo_mock.go Foo
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | isavinof |
