1

Suppose I have two packages, foo and bar (and thus, foo.go, foo_test.go, bar.go, and bar_test.go.) bar depends on foo. In bar_test.go, I want to use some faked types that are defined in foo_test.go. But since it isn't allowed for *_test.go files to export types, I moved them into a test package for foo, ie footest, that both foo and bar depend on.

Suppose foo.go has some interfaces like this:

type A interface {
   AFunc() err
}

type B interface {
   BFunc() (A, error)
}

and in footest.go, I want to implement these interfaces with fakes:

type FakeA struct {}

type FakeB struct {}

func (fa *FakeA) AFunc() error {
   // this does something
}

func (fb *FakeB) BFunc() (A, error) {
   // this does something and returns an instance of A
}

This doesn't work, because it creates a circular dependency. foo depends on footest, but footest also needs to depend on foo in order to reference A.

Am I missing some kind of best practice that would enable me to avoid this problem? I was under the impression that creating test packages, like footest, is the standard practice when test files need to use faked types in other packages, but I would love to be corrected if there's a better way.

jcgrowley
  • 709
  • 1
  • 8
  • 21

1 Answers1

7

package foo will not depend on package footest as long as you use package foo_test in your foo_test.go file. In that case, foo_test will be compiled as a separate package. However, you won't have access to non-exported types in package foo.

e.g.

foo.go

package foo

type A interface {
   AFunc() err
}

type B interface {
   BFunc() (A, error)
}

foo_test.go

package foo_test

// Add tests after importing package footest and foo

Read this answer for more details on the package naming.

A.Khan
  • 3,826
  • 21
  • 25
  • I didn't realize it was ever within best practices to put test code in a different package than the code under test. Thank you! – jcgrowley May 03 '21 at 15:35
  • Access to non-exported type could be resolved by adding a file ex. `export_test.go` in package `foo` which changes non-exported type to exported type. Ex. `var FooExportedType = fooNonExportedType` . An Example is in go language source https://cs.opensource.google/go/go/+/refs/tags/go1.19:src/io/export_test.go – JanPo Aug 30 '22 at 03:56