Simple example.
I have package xxx. This package contains:
struct C which is an argument in method of B
type A struct {
SomeField B
}
type B interface {
SomeMethod(c C)
}
Now imagine I want to create unit test for structure A and mock dependency B. For creating mock I am using mock generator. All mocks are stored in the common "mocks" folder.
The problem is that generated mock has a dependency on xxx package. This is happening because SomeMethod of interface B has argument xxx.C.
Whenever I try to import my mock structure in a_test.go it fails because of cycle import problem. xxx package importing mocks package in the a_test.go. and mocks package imports xxx package in my generated mock.
I need a peace of advice, what is the best workaround for this? Maybe my approach is not idiomatic enough. Where do you store your mocks?
To avoid the cyclic dependency, we must introduce an interface in a new package say x. This interface will have all the methods that are in struct A and are accessed by struct B.
According to above explanation, put the tests within the same package will always got into the import cycle problem, and the solution is to move it to another package.
Explanation: Import cycles. It is possible to write packages so that package A imports package B and package B imports package A. ... If you make sure that, in any import cycle, at least one of the imports is in the implementation part of a package, you will not encounter any trouble.
You need to put your test under a different package.
a.go
is under package xxx
a_test.go
is under package xxx_test
a_mock.go
is under package xxx_mock
This way a_test.go
will be dependent on xxx
and xxx_mock
and will not cause dependency cycle.
Also, a.go
and a_test.go
can be under the same folder, like this:
xxx/
- a.go
- a_test.go
mock/
- a_mock.go
Since
are all in the same package, the interface should be considered as "in-package" interface, which is invisible for code in other package. So, the mock for this interface should be IN THE SAME PACKAGE as the interface itself.
Conclusion:
PUT ALL OF THEM IN THE SAME PACKAGE.
So put the mock code generated by gomock into the same package as the interface, but not "mock" package. Example(windows version):
mockgen -source=.\foo\bar.go -destination=.\foo\bar_mock.go -package=foo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With