Что действительно необходимо вашей функции hello
- это то, что имеет функцию Foo
. Вот почему у Go есть интерфейсы. Нет ничего плохого в возврате неэкспортированного типа (на самом деле, это часто и часто правильно). Я бы сделал следующее:
package foobar
// whatever thing that has a Foo function
type FClient interface {
Foo()
}
func Hello(client FClient) {
client.Foo() // will work
}
Причина, по которой вы бы сделали это так, заключается в возможности модульного тестирования этого кода:
package foobar_test
import (
"testing"
)
type testFC struct {
callCount uint64
}
// implement interface
func (t testFC) Foo() {
testFC.callCount++
}
func TestHello(t *testing.T) {
client := testFC{}
Hello(client)
if client.callCount != 1 {
t.Fail("dependency not called")
}
}
Конечно,для более сложных зависимостей вы бы использовали такие инструменты, как mockgen или тому подобное, но вы поняли идею. По определению, тест UNIT фокусируется на одном коде UNIT. Последнее, что вам нужно сделать, чтобы протестировать модуль пакета, - создать экземпляр типа из другого пакета. Вы должны быть в состоянии высмеивать все, от чего зависит ваш код. Лучший способ сделать это - интерфейсы.