#go #testing #mocking
#Вперед #тестирование #издевательство
Вопрос:
myinterface.go
type MyInterface interface {
fun1() string
fun2() int
fun3() bool
}
func Foo(mi MyInterface) string {
return mi.fun1()
}
myinterface_test.go
type MyInterfaceImplementation struct{}
func (mi MyInterfaceImplementation) fun1() string {
return "foobar"
}
func (mi MyInterfaceImplementation) fun2() int {
return int(100)
}
func (mi MyInterfaceImplementation) fun3() bool {
return false
}
func TestFoo(t *testing.T) {
mi := MyInterfaceImplementation{}
val := Foo(mi)
if val != "foobar" {
t.Errorf("Expected 'foobar', Got %s", mi.fun1())
}
}
При написании тестов для Foo
необходимо ли выполнять имитационную реализацию интерфейса MyInterface
(поскольку это требует от нас реализации fun2
, а fun3
также которые не используются в Foo
)?
Есть ли какой-либо способ, которым мы можем писать тесты для Foo
, в которых нам просто нужно написать макет реализации fun1
, а не для fun2
и fun3
?
Кроме того, каков идеальный способ протестировать такое использование интерфейсов в Go?
Комментарии:
1. Вы можете опустить макет реализации методов, которые вам не нужны, путем встраивания интерфейса в макет. Просто имейте в виду, что если что-либо в тестируемом коде вызывает нереализованные методы, это вызовет
panic
. play.golang.org/p/wSjz5SoEHyv2. Что вы хотите протестировать?
Foo
? Тогда вам не нужно ничего имитировать, вам просто нужно передать значение, которое реализуетMyInterface
. Если у вас уже есть подобная реализацияMyInterfaceImplementation
, просто используйте это.3. Также обратите внимание, что если
Foo()
используется толькоfunc1()
метод, то он не должен ожидать значения, которое реализуетMyInterface
, только интерфейс с единственнымfunc1()
методом или даже лучше: он должен просто ожидать значение функции.
Ответ №1:
Вы должны реализовать все методы. Интерфейс — это контракт, и вам нужно выполнить этот контракт.
Если вы уверены, что методы fun2
и fun3
не будут вызываться, то это обычно означает, что ваш контракт на интерфейс слишком широк. В таком случае рассмотрите возможность извлечения fun1
в выделенный интерфейс.