Как имитировать реализацию интерфейса

#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/wSjz5SoEHyv

2. Что вы хотите протестировать? Foo ? Тогда вам не нужно ничего имитировать, вам просто нужно передать значение, которое реализует MyInterface . Если у вас уже есть подобная реализация MyInterfaceImplementation , просто используйте это.

3. Также обратите внимание, что если Foo() используется только func1() метод, то он не должен ожидать значения, которое реализует MyInterface , только интерфейс с единственным func1() методом или даже лучше: он должен просто ожидать значение функции.

Ответ №1:

Вы должны реализовать все методы. Интерфейс — это контракт, и вам нужно выполнить этот контракт.

Если вы уверены, что методы fun2 и fun3 не будут вызываться, то это обычно означает, что ваш контракт на интерфейс слишком широк. В таком случае рассмотрите возможность извлечения fun1 в выделенный интерфейс.